Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

new file: .classpath

	new file:   .gitignore
	new file:   .project
	new file:   .settings/org.eclipse.jdt.core.prefs
	new file:   License
	new file:   README.txt
	new file:   bench/data/erlang_kilim_ping_pong.xls
	new file:   bench/data/erlang_kilim_task_creation.xls
	new file:   bench/data/kilim_sunfire_pingpong.xls
	new file:   bench/erlang/bigpingpong.erl
	new file:   bench/erlang/numprocs.erl
	new file:   bench/erlang/pingpong.erl
	new file:   bench/erlang/taskstart.erl
	new file:   bench/haskell/Chain
	new file:   bench/haskell/Chain.hi
	new file:   bench/haskell/Chain.hs
	new file:   bench/haskell/Chain.o
	new file:   bench/kilim/bench/BigPingPong.java
	new file:   bench/kilim/bench/Chain.java
	new file:   bench/kilim/bench/Ex_vs_Ret.java
	new file:   bench/kilim/bench/Jetlang.java
	new file:   bench/kilim/bench/LotsOfTasks.java
	new file:   bench/kilim/bench/PingPong.java
	new file:   bench/kilim/bench/Rec.java
	new file:   bench/kilim/bench/Ring.java
	new file:   bench/kilim/bench/Sleep.java
	new file:   bench/kilim/bench/Stopwatch.java
	new file:   bench/kilim/bench/ThreadBench.java
	new file:   bench/kilim/bench/ThreadPipePingPong.java
	new file:   bench/kilim/bench/Unwind.java
	new file:   bench/kilim/bench/rmi/RMI.java
	new file:   bench/scala/BigPingPong.scala
	new file:   bench/scala/Msg.scala
	new file:   bench/scala/PingPongEx.scala
	new file:   bench/scala/oBigPingPong.scala
	new file:   build.sh
	new file:   build.xml
	new file:   docs/IFAQ.txt
	new file:   docs/internals/fiber_states.graffle
	new file:   docs/internals/fiber_states.pdf
	new file:   docs/internals/task_states.graffle
	new file:   docs/internals/task_states.pdf
	new file:   docs/internals/task_states.txt
	new file:   docs/kilim_ecoop08.pdf
	new file:   docs/manual.html
	new file:   docs/manual.txt
	new file:   docs/style.css
	new file:   docs/thread_of_ones_own.pdf
	new file:   examples/kilim/examples/Chain.java
	new file:   examples/kilim/examples/Fib.java
	new file:   examples/kilim/examples/Group.java
	new file:   examples/kilim/examples/SimpleTask.java
	new file:   examples/kilim/examples/SimpleTask2.java
	new file:   examples/kilim/examples/TimedTask.java
	new file:   examples/kilim/examples/Tree.java
	new file:   libs/asm-all-2.2.3.jar
	new file:   libs/junit.jar
	new file:   src/kilim/Cell.java
	new file:   src/kilim/Constants.java
	new file:   src/kilim/Event.java
	new file:   src/kilim/EventPublisher.java
	new file:   src/kilim/EventSubscriber.java
	new file:   src/kilim/ExitMsg.java
	new file:   src/kilim/Fiber.java
	new file:   src/kilim/Generator.java
	new file:   src/kilim/KilimException.java
	new file:   src/kilim/Mailbox.java
	new file:   src/kilim/NotPausable.java
	new file:   src/kilim/Pausable.java
	new file:   src/kilim/PauseReason.java
	new file:   src/kilim/ReentrantLock.java
	new file:   src/kilim/RingQueue.java
	new file:   src/kilim/Scheduler.java
	new file:   src/kilim/State.java
	new file:   src/kilim/Task.java
	new file:   src/kilim/TaskDoneReason.java
	new file:   src/kilim/TaskGroup.java
	new file:   src/kilim/WorkerThread.java
	new file:   src/kilim/YieldReason.java
	new file:   src/kilim/analysis/AsmDetector.java
	new file:   src/kilim/analysis/BBList.java
	new file:   src/kilim/analysis/BasicBlock.java
	new file:   src/kilim/analysis/CallWeaver.java
	new file:   src/kilim/analysis/ClassFlow.java
	new file:   src/kilim/analysis/ClassInfo.java
	new file:   src/kilim/analysis/ClassWeaver.java
	new file:   src/kilim/analysis/Detector.java
	new file:   src/kilim/analysis/FileLister.java
	new file:   src/kilim/analysis/Frame.java
	new file:   src/kilim/analysis/Handler.java
	new file:   src/kilim/analysis/IncompatibleTypesException.java
	new file:   src/kilim/analysis/MethodFlow.java
	new file:   src/kilim/analysis/MethodWeaver.java
	new file:   src/kilim/analysis/NopInsn.java
	new file:   src/kilim/analysis/Range.java
	new file:   src/kilim/analysis/TypeDesc.java
	new file:   src/kilim/analysis/Usage.java
	new file:   src/kilim/analysis/Utils.java
	new file:   src/kilim/analysis/Value.java
	new file:   src/kilim/tools/Asm.java
	new file:   src/kilim/tools/DumpClass.java
	new file:   src/kilim/tools/FlowAnalyzer.java
	new file:   src/kilim/tools/P.java
	new file:   src/kilim/tools/Weaver.java
	new file:   test.sh
	new file:   test/kilim/test/All.java
	new file:   test/kilim/test/AllNotWoven.java
	new file:   test/kilim/test/AllWoven.java
	new file:   test/kilim/test/Base.java
	new file:   test/kilim/test/TaskTestClassLoader.java
	new file:   test/kilim/test/TestBasicBlock.java
	new file:   test/kilim/test/TestExprs.java
	new file:   test/kilim/test/TestFlow.java
	new file:   test/kilim/test/TestFrame.java
	new file:   test/kilim/test/TestGenerics.java
	new file:   test/kilim/test/TestInterface.java
	new file:   test/kilim/test/TestInvalidPausables.java
	new file:   test/kilim/test/TestJSR.java
	new file:   test/kilim/test/TestLock.java
	new file:   test/kilim/test/TestMailbox.java
	new file:   test/kilim/test/TestRing.java
	new file:   test/kilim/test/TestTypeDesc.java
	new file:   test/kilim/test/TestUsage.java
	new file:   test/kilim/test/TestValue.java
	new file:   test/kilim/test/TestYield.java
	new file:   test/kilim/test/TestYieldExceptions.java
	new file:   test/kilim/test/TestYieldJSR.java
	new file:   test/kilim/test/ex/ExA.java
	new file:   test/kilim/test/ex/ExB.java
	new file:   test/kilim/test/ex/ExBasicBlock.java
	new file:   test/kilim/test/ex/ExC.java
	new file:   test/kilim/test/ex/ExCatch.java
	new file:   test/kilim/test/ex/ExD.java
	new file:   test/kilim/test/ex/ExEx.java
	new file:   test/kilim/test/ex/ExException.java
	new file:   test/kilim/test/ex/ExExpr.java
	new file:   test/kilim/test/ex/ExFlow.java
	new file:   test/kilim/test/ex/ExFrame.java
	new file:   test/kilim/test/ex/ExGenerics.java
	new file:   test/kilim/test/ex/ExInterfaceImpl.java
	new file:   test/kilim/test/ex/ExInvalid.java
	new file:   test/kilim/test/ex/ExInvalidSynchronized.java
	new file:   test/kilim/test/ex/ExJSR.j
	new file:   test/kilim/test/ex/ExPausable.java
	new file:   test/kilim/test/ex/ExTaskArgTypes.java
	new file:   test/kilim/test/ex/ExYieldBase.java
	new file:   test/kilim/test/ex/ExYieldConstants.java
	new file:   test/kilim/test/ex/ExYieldDups.java
	new file:   test/kilim/test/ex/ExYieldStack.java
	new file:   test/kilim/test/ex/ExYieldSub.j
	new file:   test/kilim/test/ex/TaskStatusCB.java
  • Loading branch information...
commit e8a4c11d078b824114d162525a6f7d573e890458 0 parents
sriram srinivasan authored
Showing with 18,080 additions and 0 deletions.
  1. +1 −0  .#d.txt
  2. +11 −0 .classpath
  3. +3 −0  .gitignore
  4. +17 −0 .project
  5. +23 −0 .settings/org.eclipse.jdt.core.prefs
  6. +24 −0 License
  7. +22 −0 README.txt
  8. BIN  bench/data/erlang_kilim_ping_pong.xls
  9. BIN  bench/data/erlang_kilim_task_creation.xls
  10. BIN  bench/data/kilim_sunfire_pingpong.xls
  11. +78 −0 bench/erlang/bigpingpong.erl
  12. +86 −0 bench/erlang/numprocs.erl
  13. +27 −0 bench/erlang/pingpong.erl
  14. +39 −0 bench/erlang/taskstart.erl
  15. BIN  bench/haskell/Chain
  16. BIN  bench/haskell/Chain.hi
  17. +39 −0 bench/haskell/Chain.hs
  18. BIN  bench/haskell/Chain.o
  19. +112 −0 bench/kilim/bench/BigPingPong.java
  20. +80 −0 bench/kilim/bench/Chain.java
  21. +65 −0 bench/kilim/bench/Ex_vs_Ret.java
  22. +50 −0 bench/kilim/bench/Jetlang.java
  23. +61 −0 bench/kilim/bench/LotsOfTasks.java
  24. +104 −0 bench/kilim/bench/PingPong.java
  25. +85 −0 bench/kilim/bench/Rec.java
  26. +81 −0 bench/kilim/bench/Ring.java
  27. +94 −0 bench/kilim/bench/Sleep.java
  28. +63 −0 bench/kilim/bench/Stopwatch.java
  29. +141 −0 bench/kilim/bench/ThreadBench.java
  30. +72 −0 bench/kilim/bench/ThreadPipePingPong.java
  31. +89 −0 bench/kilim/bench/Unwind.java
  32. +40 −0 bench/kilim/bench/rmi/RMI.java
  33. +97 −0 bench/scala/BigPingPong.scala
  34. +12 −0 bench/scala/Msg.scala
  35. +86 −0 bench/scala/PingPongEx.scala
  36. +82 −0 bench/scala/oBigPingPong.scala
  37. +22 −0 build.sh
  38. +146 −0 build.xml
  39. +302 −0 docs/IFAQ.txt
  40. +1,502 −0 docs/internals/fiber_states.graffle
  41. BIN  docs/internals/fiber_states.pdf
  42. +1,293 −0 docs/internals/task_states.graffle
  43. BIN  docs/internals/task_states.pdf
  44. +49 −0 docs/internals/task_states.txt
  45. BIN  docs/kilim_ecoop08.pdf
  46. +218 −0 docs/manual.html
  47. +210 −0 docs/manual.txt
  48. +35 −0 docs/style.css
  49. BIN  docs/thread_of_ones_own.pdf
  50. +57 −0 examples/kilim/examples/Chain.java
  51. +50 −0 examples/kilim/examples/Fib.java
  52. +29 −0 examples/kilim/examples/Group.java
  53. +54 −0 examples/kilim/examples/SimpleTask.java
  54. +49 −0 examples/kilim/examples/SimpleTask2.java
  55. +44 −0 examples/kilim/examples/TimedTask.java
  56. +82 −0 examples/kilim/examples/Tree.java
  57. BIN  libs/asm-all-2.2.3.jar
  58. BIN  libs/junit.jar
  59. +292 −0 src/kilim/Cell.java
  60. +64 −0 src/kilim/Constants.java
  61. +15 −0 src/kilim/Event.java
  62. +4 −0 src/kilim/EventPublisher.java
  63. +5 −0 src/kilim/EventSubscriber.java
  64. +33 −0 src/kilim/ExitMsg.java
  65. +348 −0 src/kilim/Fiber.java
  66. +81 −0 src/kilim/Generator.java
  67. +14 −0 src/kilim/KilimException.java
  68. +415 −0 src/kilim/Mailbox.java
  69. +5 −0 src/kilim/NotPausable.java
  70. +13 −0 src/kilim/Pausable.java
  71. +17 −0 src/kilim/PauseReason.java
  72. +70 −0 src/kilim/ReentrantLock.java
  73. +95 −0 src/kilim/RingQueue.java
  74. +137 −0 src/kilim/Scheduler.java
  75. +30 −0 src/kilim/State.java
  76. +407 −0 src/kilim/Task.java
  77. +21 −0 src/kilim/TaskDoneReason.java
  78. +49 −0 src/kilim/TaskGroup.java
  79. +62 −0 src/kilim/WorkerThread.java
  80. +18 −0 src/kilim/YieldReason.java
  81. +95 −0 src/kilim/analysis/AsmDetector.java
  82. +19 −0 src/kilim/analysis/BBList.java
  83. +1,511 −0 src/kilim/analysis/BasicBlock.java
  84. +1,038 −0 src/kilim/analysis/CallWeaver.java
  85. +132 −0 src/kilim/analysis/ClassFlow.java
  86. +16 −0 src/kilim/analysis/ClassInfo.java
  87. +227 −0 src/kilim/analysis/ClassWeaver.java
  88. +114 −0 src/kilim/analysis/Detector.java
  89. +147 −0 src/kilim/analysis/FileLister.java
  90. +295 −0 src/kilim/analysis/Frame.java
  91. +82 −0 src/kilim/analysis/Handler.java
  92. +15 −0 src/kilim/analysis/IncompatibleTypesException.java
  93. +570 −0 src/kilim/analysis/MethodFlow.java
  94. +520 −0 src/kilim/analysis/MethodWeaver.java
  95. +27 −0 src/kilim/analysis/NopInsn.java
  96. +37 −0 src/kilim/analysis/Range.java
  97. +287 −0 src/kilim/analysis/TypeDesc.java
  98. +152 −0 src/kilim/analysis/Usage.java
  99. +78 −0 src/kilim/analysis/Utils.java
  100. +187 −0 src/kilim/analysis/Value.java
  101. +832 −0 src/kilim/tools/Asm.java
  102. +369 −0 src/kilim/tools/DumpClass.java
  103. +185 −0 src/kilim/tools/FlowAnalyzer.java
  104. +38 −0 src/kilim/tools/P.java
  105. +195 −0 src/kilim/tools/Weaver.java
  106. +5 −0 test.sh
  107. +29 −0 test/kilim/test/All.java
  108. +26 −0 test/kilim/test/AllNotWoven.java
  109. +24 −0 test/kilim/test/AllWoven.java
  110. +98 −0 test/kilim/test/Base.java
  111. +74 −0 test/kilim/test/TaskTestClassLoader.java
  112. +72 −0 test/kilim/test/TestBasicBlock.java
  113. +29 −0 test/kilim/test/TestExprs.java
  114. +52 −0 test/kilim/test/TestFlow.java
  115. +146 −0 test/kilim/test/TestFrame.java
  116. +44 −0 test/kilim/test/TestGenerics.java
  117. +36 −0 test/kilim/test/TestInterface.java
  118. +56 −0 test/kilim/test/TestInvalidPausables.java
  119. +42 −0 test/kilim/test/TestJSR.java
  120. +50 −0 test/kilim/test/TestLock.java
  121. +201 −0 test/kilim/test/TestMailbox.java
  122. +49 −0 test/kilim/test/TestRing.java
  123. +146 −0 test/kilim/test/TestTypeDesc.java
  124. +55 −0 test/kilim/test/TestUsage.java
  125. +73 −0 test/kilim/test/TestValue.java
  126. +80 −0 test/kilim/test/TestYield.java
  127. +42 −0 test/kilim/test/TestYieldExceptions.java
  128. +45 −0 test/kilim/test/TestYieldJSR.java
  129. +6 −0 test/kilim/test/ex/ExA.java
  130. +5 −0 test/kilim/test/ex/ExB.java
  131. +65 −0 test/kilim/test/ex/ExBasicBlock.java
  132. +5 −0 test/kilim/test/ex/ExC.java
  133. +139 −0 test/kilim/test/ex/ExCatch.java
  134. +5 −0 test/kilim/test/ex/ExD.java
  135. +17 −0 test/kilim/test/ex/ExEx.java
  136. +9 −0 test/kilim/test/ex/ExException.java
  137. +106 −0 test/kilim/test/ex/ExExpr.java
  138. +22 −0 test/kilim/test/ex/ExFlow.java
  139. +7 −0 test/kilim/test/ex/ExFrame.java
  140. +31 −0 test/kilim/test/ex/ExGenerics.java
  141. +19 −0 test/kilim/test/ex/ExInterfaceImpl.java
  142. +47 −0 test/kilim/test/ex/ExInvalid.java
  143. +21 −0 test/kilim/test/ex/ExInvalidSynchronized.java
  144. +86 −0 test/kilim/test/ex/ExJSR.j
  145. +13 −0 test/kilim/test/ex/ExPausable.java
  146. +36 −0 test/kilim/test/ex/ExTaskArgTypes.java
  147. +95 −0 test/kilim/test/ex/ExYieldBase.java
  148. +78 −0 test/kilim/test/ex/ExYieldConstants.java
  149. +70 −0 test/kilim/test/ex/ExYieldDups.java
  150. +129 −0 test/kilim/test/ex/ExYieldStack.java
  151. +299 −0 test/kilim/test/ex/ExYieldSub.j
  152. +7 −0 test/kilim/test/ex/TaskStatusCB.java
1  .#d.txt
11 .classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="examples"/>
+ <classpathentry kind="src" path="bench"/>
+ <classpathentry kind="src" path="test"/>
+ <classpathentry kind="lib" path="libs/asm-all-2.2.3.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="libs/junit.jar"/>
+ <classpathentry kind="output" path="classes"/>
+</classpath>
3  .gitignore
@@ -0,0 +1,3 @@
+classes/**/*
+testclasses/**/*
+.DS_Store
17 .project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>kilim</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
23 .settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,23 @@
+#Mon Jul 28 11:20:18 BST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
24 License
@@ -0,0 +1,24 @@
+======================================================================
+This license is a copy of the MIT license.
+- Sriram Srinivasan (kilim@malhar.net)
+======================================================================
+Copyright (c) 2006 Sriram Srinivasan
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 README.txt
@@ -0,0 +1,22 @@
+Kilim v0.5
+Copyright (c) 2006 Sriram Srinivasan.
+(kilim _at_ malhar.net)
+======================================================================
+
+This software is released under an MIT-style licesne (please see the
+License file).
+
+Please see docs/manual.txt and docs/kilim_ecoop08.pdf for a brief
+introduction.
+
+This software depends on the ASM bytecode library (v 3.0).
+
+To build, you can either run "build.sh" on Unix or ant from the top
+directory. Run "test.sh" or "ant test" to test.
+
+To run an example, type (say)
+ java -cp ./classes:$CLASSPATH kilim.examples.Chain 10
+
+Please send comments, queries, code fixes, constructive criticisms to
+kilim _at_ malhar.net
+
BIN  bench/data/erlang_kilim_ping_pong.xls
Binary file not shown
BIN  bench/data/erlang_kilim_task_creation.xls
Binary file not shown
BIN  bench/data/kilim_sunfire_pingpong.xls
Binary file not shown
78 bench/erlang/bigpingpong.erl
@@ -0,0 +1,78 @@
+-module(bigpingpong).
+-export([bench/1, start/1, recv/2]).
+
+% Create N procs. Each proc sends a message to every other (n-1),
+% and waits for n-1 msgs from the others, before signalling
+% to a collector proc that it is done. Elapsed time is measured.
+% N procs => Num Msgs = n(n+1). (Including extra msg initially
+% to each proc to start.
+
+bench(N) -> bench(10, N). % Run benchmark 10 times
+
+bench(0, _) -> done;
+bench(M, N) ->
+ start(N),
+ % Wait a little for possible background cleanup to occur
+ receive
+ after 1000
+ -> done
+ end,
+ bench(M-1, N).
+
+start(NumProcesses) ->
+ statistics(runtime),
+ Pids = spawnN(NumProcesses, NumProcesses, self(), []),
+ lists:foreach(
+ fun(Pid) ->
+ Pid ! {start, Pids}
+ end,
+ Pids),
+ wait(NumProcesses, NumProcesses).
+
+wait(0, _) -> %wait(0, OrigN) ->
+ {_, T} = statistics(runtime),
+% if T == 0 ->
+% io:format("Elapsed: ~p ms ~n", [T]);
+% true ->
+% io:format("Elapsed: ~p ms, ~p tasks/ms ~n", [T, OrigN/T])
+% end;
+ io:format("~p~n", [T]);
+
+wait(N, OrigN) ->
+ receive
+ done ->
+ wait(N-1, OrigN)
+ end.
+
+
+% Spawn N procs and return list of pids
+spawnN(0, _, _, ListAlreadySpawned) -> ListAlreadySpawned;
+spawnN(N, OrigN, MainPid, ListAlreadySpawned) ->
+ Pid = spawn(bigpingpong, recv, [MainPid, OrigN]),
+ spawnN(N-1, OrigN, MainPid, [Pid|ListAlreadySpawned]).
+
+% Rcv
+recv(_, 1) -> done; % Done after n-1 msgs
+recv(MainPid, OrigN) ->
+ receive
+ {start, Pids} ->
+ lists:foreach(
+ fun(E) ->
+ if
+ % Skip self
+ not (E == self()) ->
+ E ! ping;
+ true -> pass
+ end
+ end,
+ Pids),
+ MainPid ! done,
+ recv(MainPid, OrigN);
+
+ ping ->
+ $ wait for n-1 msgs
+ recv(MainPid, OrigN-1)
+ end.
+
+
+
86 bench/erlang/numprocs.erl
@@ -0,0 +1,86 @@
+-module(numprocs).
+-export([bbench/1, bench/1, bench/2, start/1, start/2, recv/1]).
+
+
+% create N processes, wait for them to send a msg and die.
+% bench repeats this experiments a few times
+bench(N) -> bench(10, N).
+
+
+% spawn N processes that block. Measure time taken to spawn. Not
+% a good round-trip test.
+% bbench repeats this experiments a few times
+bbench(N) -> bbench(10, N).
+
+%======================================================================
+
+bench(0,_) -> done;
+bench(M,N) ->
+ start(N),
+ % Wait a little for possible background cleanup to occur
+ receive
+ after 1000
+ -> done
+ end,
+ bench(M-1, N).
+
+bbench(0, _) -> done;
+bbench(M, N) ->
+ start(N, block),
+ receive
+ after 1000 -> done
+ end,
+ bbench(M-1, N).
+
+start(N) ->
+ statistics(runtime),
+ %io:format("spawning ~p procs~n", [N]),
+ spawnN(N, self()),
+ %io:format("waiting for them to finish~n"),
+ wait(N, N).
+
+start(N, block) ->
+ statistics(runtime),
+ spawnN(N, nil),
+ {_, T} = statistics(runtime),
+ if T == 0 ->
+ %io:format("Elapsed: ~p ms ~n", [T]);
+ io:format("~p~n", [T]);
+ true ->
+ %io:format("Elapsed: ~p ms, ~p tasks/ms ~n", [T, N/T])
+ io:format("~p~n", [T])
+ end.
+
+wait(0, _) -> %wait(0, Total) ->
+ {_, T} = statistics(runtime),
+ if T == 0 ->
+ %io:format("Elapsed: ~p ms ~n", [T]);
+ io:format("~p~n", [T]);
+ true ->
+ %io:format("Elapsed: ~p ms, ~p tasks/ms ~n", [T, Total/T])
+ io:format("~p~n", [T])
+ end;
+wait(N, Total) ->
+ receive
+ done ->
+ wait(N-1, Total)
+ end.
+
+
+spawnN(0, _) -> done;
+spawnN(N, Main) ->
+% if (N rem 50000 == 0) ->
+% io:format("#Procs: ~p ~n", [N]);
+% true -> true
+% end,
+ spawn(numprocs, recv, [Main]),
+ spawnN(N-1, Main).
+
+recv(Main) ->
+ if is_pid(Main) ->
+ Main ! done;
+ true ->
+ receive
+ hello -> recv(Main)
+ end
+ end.
27 bench/erlang/pingpong.erl
@@ -0,0 +1,27 @@
+-module(pingpong).
+-export([start/0, ping/3, pong/0]).
+
+start() ->
+ Pong = spawn(pingpong, pong, []),
+ spawn(pingpong, ping, [Pong, erlang:now(), 100000]).
+
+ping(_, StartTime, 0) ->
+ io:format("Elapsed: ~p~n", [timer:now_diff(erlang:now(), StartTime)]);
+
+ping(Pong, StartTime, N) ->
+ %io:format("ping ~p~n", [N]),
+ Pong ! {ping, self()},
+ receive
+ pong ->
+ ping(Pong, StartTime, N-1)
+ end.
+
+
+pong() ->
+ receive
+ {ping, Ping} ->
+ %io:format("Received ping~n"),
+ Ping ! pong,
+ pong()
+ end.
+
39 bench/erlang/taskstart.erl
@@ -0,0 +1,39 @@
+-module(taskstart).
+-export([start/0, startRound/1, launch/1]).
+
+start() ->
+ Reporter = spawn(taskstart, startRound, [10]),
+ register(reporter, Reporter).
+
+%---------------------------------------------------------------------
+% Reporter
+% Spawns a ring in each of n rounds, and waits for the ring
+% to signal completion.
+%---------------------------------------------------------------------
+startRound(0)->
+ erlang:halt();
+
+startRound(N)->
+ StartTime = erlang:now(),
+ spawn(taskstart, launch, [100000]),
+ receive
+ EndTime ->
+ io:format("~p ~p~n", [N, timer:now_diff(EndTime, StartTime)])
+ end,
+ startRound(N-1).
+
+%---------------------------------------------------------------------
+%Ring
+% Each process m spawns process m-1. The last process sends the
+% current time to the reporter.
+%---------------------------------------------------------------------
+
+launch(0) ->
+ EndTime = erlang:now(),
+ whereis(reporter) ! EndTime;
+
+launch(M) ->
+ spawn(taskstart, launch, [M-1]).
+
+
+
BIN  bench/haskell/Chain
Binary file not shown
BIN  bench/haskell/Chain.hi
Binary file not shown
39 bench/haskell/Chain.hs
@@ -0,0 +1,39 @@
+-- Set up n threads in a chain. Each thread retrieves from its MVar and
+-- dumps that value on the next MVar
+
+-- This benchmark adapted from Bryan O'Sullivan's blog. The difference is
+-- that the threads are each given their own MVar to reduce contention.
+
+-- Compile with ghc -O2 --make Chain.hs
+-- Run ./Chain 100000
+-- Compare to java kilim.bench.Chain -ntasks 100000 -nmsgs 1
+
+module Main where
+
+import Control.Applicative
+import Control.Concurrent.MVar
+import Control.Concurrent
+import System.Environment
+import Data.Time
+
+main = do
+ mv <- newEmptyMVar
+ start <- getCurrentTime
+ lastmv <- (loop mv =<< read . head <$> getArgs)
+ end <- getCurrentTime
+ putStrLn $ "creation time: " ++ show (diffUTCTime end start)
+ putMVar mv 0
+ lastnum <- takeMVar lastmv
+ fin <- getCurrentTime
+ putStrLn $ "message time: " ++ show (diffUTCTime fin end)
+ putStrLn $ "Threads: " ++ show lastnum
+
+loop :: MVar Int -> Int -> IO (MVar Int)
+loop mv n | n <= 0 = return mv
+ | otherwise = do
+ nextmv <- newEmptyMVar
+ forkIO $ do
+ m <- takeMVar mv
+ putMVar nextmv $! m+1
+ loop nextmv $! n-1
+
BIN  bench/haskell/Chain.o
Binary file not shown
112 bench/kilim/bench/BigPingPong.java
@@ -0,0 +1,112 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+import kilim.*;
+public class BigPingPong extends Task {
+ static Mailbox<Msg>[] mboxes;
+ static Mailbox<Msg> mainmb;
+
+
+ @SuppressWarnings("unchecked")
+ public static void main(String args[]) throws Exception {
+ boolean noargs = args.length == 0;
+ int nTasks = noargs ? 10 : Integer.parseInt(args[0]);
+ int nSchedulers = noargs ? 1 : Integer.parseInt(args[1]);
+ int nThreadsPerScheduler = noargs ? 1 : Integer.parseInt(args[2]);
+ Scheduler [] schedulers = new Scheduler[nSchedulers];
+
+ System.out.println("nTasks : " + nTasks + ", nSchedulers: " + nSchedulers +
+ ", nThreadsPerScheduler: " + nThreadsPerScheduler);
+
+ for (int c = 0; c < 13; c++) { // Timing loop
+ long beginTime = System.currentTimeMillis();
+ mboxes = new Mailbox[nTasks];
+// mainmb = new Mailbox<Msg>(/* initial size = */ nTasks);
+ mainmb = new Mailbox<Msg>(/* initial size = */ nTasks, nTasks);
+ for (int i = 0; i < nTasks; i++) {
+ mboxes[i] = new Mailbox<Msg>(/* initial size = */ nTasks, nTasks);
+ }
+
+ for (int i = 0 ; i < nSchedulers; i++) {
+ schedulers[i] = new Scheduler(nThreadsPerScheduler);
+ }
+
+ BigPingPong[] tasks = new BigPingPong[nTasks];
+
+ for (int i = 0; i < nTasks; i++) {
+ BigPingPong t = new BigPingPong(i);
+ tasks[i] = t;
+ t.setScheduler(schedulers[i % nSchedulers]);
+ t.start();
+ }
+
+ for (int i = 0; i < nTasks; i++) {
+// mainmb.getWait();
+ Msg m = mainmb.getb(20000);
+// Msg m = mainmb.getb();
+ if (m == null) {
+ System.err.println("TIME OUT (20s). No of tasks finished: " + i);
+// for (BigPingPong t: tasks) {
+// System.err.println(t);
+// }
+// for (Mailbox mb: mboxes) {
+// System.err.println(mb);
+// }
+ System.exit(1);
+ }
+ }
+ // Total number of messages: from each task to every other task,
+ // and finally one to the main mailbox to signal completion
+ // nTasks * (nTasks - 1) + nTasks
+ int nMessages = nTasks * nTasks;
+ System.out.println("Elapsed ms (" + nTasks + " tasks, " +
+ nMessages + " messages) " + (System.currentTimeMillis() - beginTime));
+ System.gc();
+ Thread.sleep(1000);
+ for (int i = 0; i < nSchedulers; i++) {
+ schedulers[i].shutdown();
+ }
+ }
+ }
+
+ int n; // Task's position in the slot array
+ BigPingPong(int num) {
+ n = num;
+ }
+
+ boolean done = false;
+ int numRcvd = 0;
+
+ public void execute() throws Pausable {
+ done = false;
+ int l = mboxes.length;
+ Msg mymsg = new Msg(id);
+
+ int me = n;
+ Mailbox<Msg> mymb = mboxes[me];
+
+ for (int i = 0; i < l; i++) {
+ if (i == me)
+ continue;
+ mboxes[i].put(mymsg);
+ }
+ for (int i = 0; i < l - 1; i++) {
+ Msg m = mymb.get();
+ assert m != null;
+ numRcvd++;
+ }
+ mainmb.put(mymsg);
+ done = true;
+ }
+
+ private static class Msg {
+ static Msg gMsg = new Msg(0);
+ int from;
+ Msg(int f) {from = f;}
+ };
+}
+
80 bench/kilim/bench/Chain.java
@@ -0,0 +1,80 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.*;
+
+public class Chain extends Task {
+ static class Mbx extends Mailbox<Integer>{}
+ static int nTasks = 500;
+ static int nMsgs = 10000;
+
+ Mbx mymb, nextmb;
+ static long startTime;
+
+
+ public static void main(String[] args) {
+ Scheduler.setDefaultScheduler(new Scheduler(2)); // 2 threads.
+ try {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equalsIgnoreCase("-nMsgs")) {
+ nMsgs = Integer.parseInt(args[++i]);
+ } else if (arg.equalsIgnoreCase("-nTasks")) {
+ nTasks = Integer.parseInt(args[++i]);
+ }
+ }
+ }
+ catch (NumberFormatException e) {
+ System.err.println("Integer argument expected");
+ }
+ System.out.println("Num tasks in chain: " + nTasks + ". Num messages sent:" + nMsgs);
+ bench(nMsgs, nTasks);
+ }
+
+ static void bench(int nMsgs, int nTasks) {
+ startTime = System.currentTimeMillis();
+
+ Mbx mb = new Mbx();
+ Mbx nextmb = null;
+ // Create a chain of tasks.
+ for (int i = 0; i < nTasks; i++) {
+ new Chain(mb, nextmb).start();
+ nextmb = mb;
+ mb = new Mbx();
+ }
+ for (int i = 0; i < nMsgs; i++) {
+ nextmb.putnb(0); // enqueue a message for the head of the chain.
+ }
+ }
+
+ public Chain(Mbx mb, Mbx next) {
+ mymb = mb;
+ nextmb = next;
+ }
+
+ int numReceived = 0;
+
+ public void execute() throws Pausable {
+ while (true) {
+// System.out.println("Waiting: # " + id());
+ Integer val = mymb.get();
+// System.out.println("GET ===== # " + id());
+ if (nextmb == null) {
+ numReceived++;
+ if (numReceived == nMsgs) {
+ System.out.println("Elapsed time: " +
+ (System.currentTimeMillis() - startTime)
+ + " ms ");
+ System.exit(0);
+ }
+ } else {
+ nextmb.put(val);
+ }
+ }
+ }
+}
65 bench/kilim/bench/Ex_vs_Ret.java
@@ -0,0 +1,65 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+public class Ex_vs_Ret {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ final int ntimes = 1000000;
+ final int depth = 10;
+
+ // JIT Warmup ===========================================
+ for (int i = 0; i < 1000; i++) ret(depth);
+ for (int i = 0; i < 1000; i++) {
+ try {
+ ex(depth);
+ } catch (FastEx ignore) {}
+ }
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < ntimes; i++) {
+ ret(depth);
+ }
+ long elapsed = System.currentTimeMillis() - start;
+ System.out.println("Iterations = : " +ntimes + ", stack depth = " + depth);
+ System.out.println("ret ms: " + elapsed);
+
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ntimes; i++) {
+ try {
+ ex(depth);
+ } catch (FastEx fe) {}
+ }
+ elapsed = System.currentTimeMillis() - start;
+ System.out.println("ex : " + elapsed);
+ }
+
+ static void ret(int depth) {
+ if (depth != 0) {
+ ret(depth-1);
+ }
+ }
+
+ static void ex(int depth) throws FastEx {
+ if (depth == 0) {
+ throw new FastEx();
+ }
+ ex(depth-1);
+ }
+}
+
+final class FastEx extends Throwable {
+ private static final long serialVersionUID = 1L; // Just suppressing warnings.
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return null; // The most time consuming part of throwing an exception.
+ }
+}
50 bench/kilim/bench/Jetlang.java
@@ -0,0 +1,50 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+import kilim.Mailbox;
+import kilim.Pausable;
+import kilim.Task;
+/**
+ * Compare this to Jetlang's PerfMain tests
+ * See http://code.google.com/p/jetlang/
+ */
+public class Jetlang extends Task {
+ @SuppressWarnings("unchecked")
+
+ /* limit number of msgs in mailbox */
+ static Mailbox<Integer> mb = new Mailbox<Integer>(1000,1000);
+ final static int max = 5000000;
+
+ public static void main(String args[]) throws Exception {
+ Stopwatch s = new Stopwatch();
+ s.tick();
+
+ Task t = new Jetlang().start();
+ new Publisher().start();
+ t.joinb(); // wait for receiver to finish
+
+ s.tickPrint(max+1); // same number of iterations as jetlang's tests.
+ }
+
+ public void execute() throws Pausable {
+ while (true) {
+ int i = mb.get();
+ if (i == max) {
+ break;
+ }
+ }
+ }
+
+ static class Publisher extends Task {
+ public void execute() throws Pausable {
+ for (int i = 0; i <= max; i++) {
+ mb.put(i);
+ }
+ }
+ }
+}
+
61 bench/kilim/bench/LotsOfTasks.java
@@ -0,0 +1,61 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.*;
+
+public class LotsOfTasks {
+ static boolean block;
+ public static void main(String[] args) throws Exception {
+ // Usage: java kilim.bench.LotsOfTasks [ntasks] [pause]
+ // pause will tell each task to wait on its mailbox
+
+ final int numTasks = (args.length > 0) ? Integer.parseInt(args[0]) : 100000;
+ final boolean block = (args.length > 1) ? true : false;
+ final Stopwatch s = new Stopwatch("Tasks(" + numTasks + ")");
+ for (int round = 0; round < 10; round++) {
+ s.tick();
+ final Mailbox<ExitMsg> exitmb = new Mailbox<ExitMsg>();
+
+ System.out.println("Creating " + numTasks + (block ? " blocking tasks" : " tasks"));
+ for (int i = 1; i <= numTasks; i++) {
+ Task t = new LTask();
+ t.informOnExit(exitmb);
+ t.start();
+ if (i % 100000 == 0) {
+ System.out.println("Created " + i + " tasks .... (contd.)");
+ }
+ }
+
+ if (block) {
+ for (int i = 1; i <= numTasks; i++) {
+ exitmb.getb();
+ if (i % 100000 == 0) {
+ System.out.println("Created " + i + " tasks .... (contd.)");
+ }
+ };
+ }
+ System.out.println("Round #" + round + " done. " + numTasks + " created in " + s.tick() + " ms");
+ s.tickPrint(numTasks);
+ System.gc();
+ Thread.sleep(1000); // give the GC a chance.
+ }
+ System.exit(0);
+ }
+
+}
+
+class LTask extends Task {
+ Mailbox<String> mymb = new Mailbox<String>();
+
+ public void execute() throws Pausable {
+ if (LotsOfTasks.block) {
+ mymb.get();
+ }
+ }
+
+}
104 bench/kilim/bench/PingPong.java
@@ -0,0 +1,104 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.Mailbox;
+import kilim.Pausable;
+import kilim.Task;
+/*
+ * This code is unnecessarily long for what it aims to do: bounce a message back
+ * and forth between two tasks for a certain number of times. The reason for the
+ * length is to compare against a similar example in the scala distribution.
+ */
+public class PingPong {
+
+ public static void main(String[] args) {
+ Mailbox<Msg> pingmb = new Mailbox<Msg>();
+ Mailbox<Msg> pongmb = new Mailbox<Msg>();
+ new Ping(pingmb, pongmb).start();
+ new Pong(pongmb).start();
+ pingmb.putnb(new Msg(MsgType.Init, 100000, null));
+ pingmb.putnb(new Msg(MsgType.Start, pingmb));
+ }
+}
+
+class Ping extends Task {
+ Mailbox<Msg> mymb;
+ Mailbox<Msg> pongmb;
+ int origcount;
+ int count;
+ long beginTime;
+ Ping(Mailbox<Msg> mb, Mailbox<Msg> pong) {
+ mymb = mb;
+ pongmb = pong;
+ }
+
+ public void execute() throws Pausable {
+ while (true) {
+ Msg m = mymb.get();
+ switch(m.type) {
+ case Init:
+ origcount = count = m.count;
+ beginTime = System.currentTimeMillis();
+ break;
+ case Start:
+ case PongMsg:
+ if (count > 0) {
+// System.out.println("Ping: " + m + " " + count); System.out.flush();
+// pongmb.put(new Msg(MsgType.PingMsg, mymb));
+ m.type = MsgType.PingMsg;
+ pongmb.put(m);
+ count--;
+ } else {
+ long elapsed = System.currentTimeMillis() - beginTime;
+ System.out.println("Total time: " + elapsed + " millis, "
+ + origcount + " rounds");
+ System.out.println("Time to send msg + context switch: " +
+ (elapsed * 1000.0 / 2 / origcount) + " micros");
+ System.exit(0);
+ }
+ break;
+ }
+ }
+ }
+}
+
+class Pong extends Task {
+ Mailbox<Msg> mymb;
+ Pong(Mailbox<Msg> mb) {
+ mymb = mb;
+ }
+
+ public void execute() throws Pausable {
+ while (true) {
+ Msg m = mymb.get();
+// System.out.println("Pong: " + m); System.out.flush();
+ switch(m.type) {
+ case PingMsg:
+// m.mb.put(new Msg(MsgType.PongMsg, null));
+ m.type = MsgType.PongMsg;
+ m.mb.put(m);
+ break;
+ }
+ }
+ }
+}
+
+
+enum MsgType {Init, Start, PingMsg, PongMsg};
+
+class Msg {
+ MsgType type;
+ Mailbox<Msg> mb;
+ int count; // for init
+ Msg(MsgType t, int c, Mailbox<Msg> amb) {type = t; mb = amb; count = c;}
+ Msg(MsgType t, Mailbox<Msg> amb) {type = t; mb = amb;}
+
+ public String toString() {
+ return "" + System.identityHashCode(this) + " " + type;
+ }
+}
85 bench/kilim/bench/Rec.java
@@ -0,0 +1,85 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.*;
+
+public class Rec extends Task {
+ static boolean pause = false;
+ static boolean pausable = false;
+ public static void main(String[] args) throws Exception {
+ int n = Integer.parseInt(args[0]);
+ int d = Integer.parseInt(args[1]);
+
+ pausable = true;
+
+ pause = true;
+ testCont(new Rec(5,5));
+ long tpause = testCont(new Rec(n, d));
+
+ pause = false;
+ testCont(new Rec(5,5));
+ long tnopause = testCont(new Rec(n, d));
+
+ pausable = false;
+ testCont(new Rec(5, 5));
+ long tbase = testCont(new Rec(n, d));
+ System.out.println(n + " " + tbase + " " + tnopause + " " + tpause);
+ }
+
+ public static long testCont(Rec ex) throws NotPausable, Exception {
+ long start = System.currentTimeMillis();
+ if (pausable) {
+ Fiber f = new Fiber(ex);
+ while (true) {
+ ex.execute(f.begin());
+ if (f.end()) break;
+ }
+ } else {
+ ex.noPauseRun();
+ }
+ return (System.currentTimeMillis() - start);
+ }
+
+
+ int n;
+ int depth;
+ public Rec(int an, int aDepth) {
+ n = an;
+ depth = aDepth;
+ }
+
+ public void execute() throws Pausable {
+ for (int i = 0; i < n; i++) {
+ rec(depth, "foo");
+ }
+ }
+
+ public void noPauseRun() {
+ for (int i = 0; i < n; i++) {
+ recNoPause(depth, "foo");
+ }
+ }
+
+ private void rec(int d, String s) throws Pausable {
+ if (d == 1) {
+ if (pause) {
+ Task.yield();
+ }
+ return;
+ }
+ rec(d-1, s);
+ }
+
+ private void recNoPause(int d, String s) {
+ if (d == 1) {
+ return;
+ }
+ recNoPause(d-1, s);
+ }
+
+}
81 bench/kilim/bench/Ring.java
@@ -0,0 +1,81 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.*;
+
+public class Ring extends Task {
+ Mailbox<String> mb;
+ Mailbox<String> prev;
+ int times; // num times already gone around. When 0, won't pass it on.
+ int num; // this task's number
+
+ public static boolean logging = false;
+ static long startTime;
+ public static void main(String[] args) {
+ int n = 10; // num elements in ring.
+ int t = 100000; // num times around ring
+ try {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equals("-n")) {
+ n = Integer.parseInt(args[++i]);
+ } else if (arg.equals("-t")) {
+ t = Integer.parseInt(args[++i]);
+ } else if (arg.equals("-l")) {
+ logging = true;
+ }
+ }
+ }
+ catch (NumberFormatException e) {
+ System.err.println("Integer argument expected");
+ }
+ if (logging) System.out.println("Started");
+ Mailbox<String> mb = new Mailbox<String>();
+ Mailbox<String> startmb = mb;
+ Ring r = new Ring(mb, null, 0, t);
+ r.start();
+ Ring start = r;
+ Mailbox<String> prevmb = mb;
+ for (int i = 1; i < n; i++) {
+ mb = new Mailbox<String>();
+ new Ring(mb, prevmb, i, t).start();
+ prevmb = mb;
+ }
+ start.prev = prevmb;
+ startTime = System.currentTimeMillis();
+ startmb.putnb("ring");
+ }
+
+ public Ring(Mailbox<String> amb, Mailbox<String> prevms,int anum, int atimes) {
+ mb = amb;
+ num = anum;
+ times = atimes;
+ prev = prevms;
+ if (logging) {
+ System.out.println("Proc# " + anum);
+ }
+ }
+
+ public void execute() throws Pausable {
+ while (true) {
+ String m = mb.get();
+ if (logging)
+ System.out.println(" Proc # " + num + ", iters left = " + times);
+ if (--times == 0) {
+ if (num == 1) { // last process
+ long elapsedTime = System.currentTimeMillis() - startTime;
+ System.out.println("Elapsed time: " + elapsedTime + " ms");
+ System.exit(0);
+ }
+ }
+ prev.put(m);
+ }
+ }
+}
+
+
94 bench/kilim/bench/Sleep.java
@@ -0,0 +1,94 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.*;
+
+
+public class Sleep extends Task {
+ static boolean pause = false;
+ static boolean pausable = false;
+ public static void main(String[] args) throws Exception {
+ int n = Integer.parseInt(args[0]);
+
+ sleep(); // waste
+ pausable = true;
+
+ pause = true;
+ testCont(new Sleep(50));
+ long tpause = testCont(new Sleep(n));
+
+ pause = false;
+ testCont(new Sleep(50));
+ long tnopause = testCont(new Sleep(n));
+
+ pausable = false;
+ testCont(new Sleep(50));
+ long tbase = testCont(new Sleep(n));
+
+// System.out.println(n + " " + tbase + " " + tnopause + " " + tpause);
+ System.out.println("n = " + n + " Not pausable: " + (tbase) + ", Not pausing: " + (tnopause) + ", Pausing: " + (tpause));
+ }
+
+ public static long testCont(Sleep ex) throws Exception {
+ System.gc();
+ try {Thread.sleep(100);}catch (Exception e) {}
+
+ long start = System.currentTimeMillis();
+ if (pausable) {
+ // Manually doing what the scheduler would do, just to cut out the
+ // thread scheduling.
+ Fiber f = new Fiber(ex);
+ while (true) {
+ ex.execute(f.begin());
+ if (f.end()) break;
+ }
+ } else {
+ ex.noPauseRun();
+ }
+ return (System.currentTimeMillis() - start);
+ }
+
+ int n;
+ public Sleep(int an) {
+ n = an;
+ }
+
+ public void execute() throws Pausable {
+ Fiber.pause();
+ for (int i = 0; i < n; i++) {
+ echo(i);
+ }
+ }
+
+ private void echo(int x) throws Pausable {
+ sleep();
+ if (pause) {
+ Fiber.pause();
+ }
+ }
+
+ public void noPauseRun() {
+ for (int i = 0; i < n; i++) {
+ echoNoPause(i);
+ }
+ }
+
+ public void echoNoPause(int x) {
+ sleep();
+ }
+
+ static void sleep() {
+// for (int i = 500000;i >= 0; i--) {
+// nop();
+// }
+ try {Thread.sleep(1);}catch(Exception e) {}
+ }
+
+ public static void nop() {}
+
+}
63 bench/kilim/bench/Stopwatch.java
@@ -0,0 +1,63 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+public class Stopwatch {
+ long lastTickMillis = System.currentTimeMillis();
+ long lastElapsedMillis = 0;
+ int multiplier = 1; // see reportMicros
+ String unit = " ms";
+ String name = "";
+
+
+ public Stopwatch() {tick();}
+ public Stopwatch(String nm) {name = nm; tick();}
+
+ /**
+ * @return the diff in millis from the last tick. Both tick and elapsed times are
+ * kept in millis
+ */
+ public long tick() {
+ long l = lastTickMillis;
+ lastTickMillis = System.currentTimeMillis();
+ lastElapsedMillis = lastTickMillis - l;
+ return lastElapsedMillis;
+ }
+
+ /**
+ * Report in micros or millis
+ */
+ public void reportMicros() {multiplier = 1000; unit = " micros";}
+ public void reportMillis() {multiplier = 1; unit = " ms";}
+
+ public long timePerIter(int iters) {
+ return iters == 0? 0 : lastElapsedMillis*multiplier/iters;
+ }
+
+ long itersPerTime(int iters) {
+ return lastElapsedMillis == 0 ? iters : iters/(lastElapsedMillis*multiplier);
+ }
+
+ public String toString() {
+ return name + ": elapsed: " + (lastElapsedMillis * multiplier) + " " + unit;
+ }
+
+ public String toString(int iters) {
+ return name + " elapsed: " + (lastElapsedMillis * multiplier) +
+ unit +", iters = " + iters +
+ ", " + unit + "/iter = " + timePerIter(iters) +
+ ", iters/" + unit + " = " + itersPerTime(iters);
+ }
+
+ public void print() {System.out.println(this);}
+
+ public void print(int iters) { System.out.println(this.toString(iters));}
+
+ public void tickPrint() {tick(); print();}
+
+ public void tickPrint(int iters) {tick(); print(iters);}
+}
141 bench/kilim/bench/ThreadBench.java
@@ -0,0 +1,141 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+public class ThreadBench extends Thread {
+ ThreadBench next;
+ int val = -1; // This value is filled by the previous process before this process is
+
+ public static boolean tracing = false;
+ static long startTime;
+
+ public static void main(String[] args) {
+ int n = 500;
+ int k = 10000;
+ try {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equals("-k")) {
+ k = Integer.parseInt(args[++i]);
+ } else if (arg.equals("-n")) {
+ n = Integer.parseInt(args[++i]);
+ } else if (arg.equals("-t")) {
+ tracing = true;
+ }
+ }
+ }
+ catch (NumberFormatException e) {
+ System.err.println("Integer argument expected");
+ }
+ startTime = System.currentTimeMillis();
+ bench(k, n);
+ }
+
+ static void bench(int k, int n) {
+ Sink sink = new Sink();
+ ThreadBench next = sink;
+ for (int i = n; i >= 1; i--) {
+ next.start();
+ next = new Copy(i, next);
+ }
+ next.start();
+ Source source = new Source(k, next);
+ sink.source = source;
+ source.start();
+ try {
+ source.join();
+ } catch (InterruptedException ie) {}
+ System.out.println("Done");
+ }
+
+ ThreadBench() {
+ }
+
+ synchronized void write(int v) {
+ while (val != -1) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {ie.printStackTrace();}
+ }
+ val = v;
+ notify();
+ }
+
+ synchronized int read() {
+ while (val == -1) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {ie.printStackTrace();}
+ }
+ int v = val;
+ val = -1;
+ notify();
+ return v;
+ }
+
+ static class Copy extends ThreadBench {
+ int id;
+ // woken up
+ Copy(int aid, ThreadBench p) {
+ id = aid;
+ next = p;
+ }
+
+ public void run() {
+ while (true) {
+ int v = read();
+ if (tracing)
+ System.out.println(this.toString() + " copying number " + v);
+ next.write(v);
+ if (v == 0) break;
+ }
+ }
+ public String toString() {return "copy " + id;}
+ }
+
+ static class Sink extends ThreadBench {
+ ThreadBench source;
+ public void run() {
+ int v;
+ int i = 0;
+ while (true) {
+ v = read();
+ i++;
+ if(tracing)
+ System.out.printf("sink: receiving number %d\n-----\n", v);
+ if (v == 0) {
+ System.out.println("Elapsed time: " +
+ (System.currentTimeMillis() - startTime)
+ + " ms, iterations = " + i);
+ System.exit(0);
+ }
+ }
+ }
+ public String toString() {return "sink";}
+ }
+
+ static class Source extends ThreadBench {
+ int loops;
+
+ Source(int k, ThreadBench p) {
+ loops = k;
+ next = p;
+ }
+
+ public void run() {
+ for (int i = 1; i <= loops; i++) {
+ if(tracing)
+ System.out.printf("source: sending number %d\n", i);
+ next.write(i);
+ }
+ // Kill
+ next.write(0);
+ }
+ public String toString() {return "source";}
+ }
+}
+
72 bench/kilim/bench/ThreadPipePingPong.java
@@ -0,0 +1,72 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+
+// Create two threads, have a message ping pong between them using pipes.
+public class ThreadPipePingPong {
+ public static void main(String args[]) throws Exception {
+ int ntimes = args.length == 0 ? 1000 : Integer.parseInt(args[0]);
+ PipedInputStream pi_in = new PipedInputStream();
+ PipedOutputStream pi_out = new PipedOutputStream();
+ PipedInputStream po_in = new PipedInputStream(pi_out);
+ PipedOutputStream po_out = new PipedOutputStream(pi_in);
+
+ PongThread po = new PongThread(po_in, po_out);
+ PingThread pi = new PingThread(ntimes, pi_in, pi_out);
+ po.start();
+ pi.start();
+ }
+}
+
+class PingThread extends Thread {
+ int ntimes;
+ PipedInputStream in;
+ PipedOutputStream out;
+ PingThread(int n, PipedInputStream i, PipedOutputStream o) {
+ ntimes = n;
+ in = i;
+ out = o;
+ }
+ public void run() {
+ try {
+ long begin = System.currentTimeMillis();
+ for (int i = 0; i < ntimes; i++) {
+ out.write(100); out.flush(); //ping
+ in.read(); // wait for pong
+ }
+ System.out.println("Elapsed (" + ntimes + " iters) : " +
+ (System.currentTimeMillis() - begin) + " millis");
+ System.exit(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
+class PongThread extends Thread {
+ PipedInputStream in;
+ PipedOutputStream out;
+
+ PongThread(PipedInputStream i, PipedOutputStream o) {
+ in = i;
+ out = o;
+ }
+ public void run() {
+ try {
+ while (true) {
+ in.read();
+ out.write(200); out.flush();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
89 bench/kilim/bench/Unwind.java
@@ -0,0 +1,89 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench;
+
+import kilim.*;
+
+
+public class Unwind extends Task {
+ static boolean pause = false;
+ static boolean pausable = false;
+ public static void main(String[] args) throws Exception {
+ int n = Integer.parseInt(args[0]);
+ pausable = true;
+
+ pause = true;
+ testCont(new Unwind(50));
+ long tpause = testCont(new Unwind(n));
+
+ pause = false;
+ testCont(new Unwind(50));
+ long tnopause = testCont(new Unwind(n));
+
+ pausable = false;
+ testCont(new Unwind(50));
+ long tbase = testCont(new Unwind(n));
+
+// System.out.println(n + " " + tbase + " " + tnopause + " " + tpause);
+ System.out.println("n = " + n + " Not pausable: " + (tbase) + ", Not pausing: " + (tnopause) + ", Pausing: " + (tpause));
+ }
+
+ public static long testCont(Unwind ex) throws Exception {
+ System.gc();
+ try {Thread.sleep(100);}catch (Exception e) {}
+
+ long start = System.currentTimeMillis();
+ if (pausable) {
+ // Manually doing what the scheduler would do, just to cut out the
+ // thread scheduling.
+ Fiber f = new Fiber(ex);
+ while (true) {
+ ex.execute(f.begin());
+ if (f.end()) break;
+ }
+ } else {
+ ex.noPauseRun();
+ }
+ return (System.currentTimeMillis() - start);
+ }
+
+ int n;
+ public Unwind(int an) {
+ n = an;
+ }
+
+ public void execute() throws Pausable {
+ for (int i = 0; i < n; i++) {
+ echo(i);
+ }
+ }
+
+ private void echo(int x) throws Pausable {
+ long l = x - (x - 2);
+ String foo = new String("foo");
+ String bar = "bar";
+ if (pause) {
+ Task.yield();
+ }
+ foo.charAt((int)l);
+ bar.charAt((int)l);
+ }
+
+ public void noPauseRun() {
+ for (int i = 0; i < n; i++) {
+ echoNoPause(i);
+ }
+ }
+
+ public void echoNoPause(int x) {
+ long l = x - (x - 2);
+ String foo = new String("foo");
+ String bar = "bar";
+ foo.charAt((int)l);
+ bar.charAt((int)l);
+ }
+}
40 bench/kilim/bench/rmi/RMI.java
@@ -0,0 +1,40 @@
+/* Copyright (c) 2006, Sriram Srinivasan
+ *
+ * You may distribute this software under the terms of the license
+ * specified in the file "License"
+ */
+
+package kilim.bench.rmi;
+import java.rmi.*;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Hashtable;
+public class RMI {
+ public static void main(String[] args) throws Exception {
+ int ntimes = args.length == 0 ? 1000 : Integer.parseInt(args[0]);
+ Server obj = new Server();
+ Ping stub = (Ping) UnicastRemoteObject.exportObject(obj, 0);
+ Hashtable<String, String> h = new Hashtable<String, String>();
+ h.put("foo", "bar");
+ h.put("hello", "world");
+ long begin = System.currentTimeMillis();
+ for (int i = 0; i < ntimes; i++) {
+// System.out.println("Sending hash " + System.identityHashCode(h));
+ stub.ping(i);
+ }
+ System.out.println("Elapsed (" + ntimes + " iters) : " +
+ (System.currentTimeMillis() - begin) + " millis");
+ }
+}
+
+interface Ping extends Remote {
+// void ping(Hashtable<String, String> h) throws RemoteException;
+ void ping(int i) throws RemoteException;
+}
+
+class Server implements Ping {
+ public void ping(int i) throws RemoteException {
+// System.out.println(i);
+ }
+
+}
+
97 bench/scala/BigPingPong.scala
@@ -0,0 +1,97 @@
+package examples.actors
+
+/*
+Adapted from PingPongEx.scala, itself an adaption of an example
+from the scala distribution (added timing measurement).
+
+This example creates n tasks and has each send a message to the
+others. It sends the same structure (and number of messages) as the
+kilim/bench/BigPingPong example.
+*/
+import scala.actors._
+import scala.actors.Actor._
+
+object BigPingPong {
+ var beginTime: long = 0
+
+ def main(args : Array[String]): Unit = {
+ val nTasks = Integer.parseInt(args(0))
+ var i = nTasks
+ var tasks: Array[Ping] = new Array[Ping](nTasks)
+// Scheduler.impl = new SingleThreadedScheduler
+ val cTask = new Collector(nTasks);
+ cTask.start()
+
+ beginTime = System.currentTimeMillis()
+ for (val i <- 0 to nTasks-1) {
+ tasks(i) = new Ping(i)
+ }
+ for (val t <- tasks) {
+ t.setOthers(tasks, cTask)
+ t.start()
+ }
+ val p = Start()
+ for (val t <- tasks) {
+ t ! p
+ }
+ }
+}
+
+abstract class Msg
+case class PingMsg(from :int ) extends Msg
+case class Start() extends Msg
+
+class Ping(i: int) extends Actor {
+ var id : int = i
+ var tasks: Array[Ping] = Array()
+ var ctask : Collector = null
+
+ def setOthers(others: Array[Ping], ct : Collector) {
+ ctask = ct
+ tasks = others
+ }
+
+ def act(): unit = {
+ var pingsExpected : int = tasks.length - 1
+ val p = PingMsg(id)
+ loop {
+ react {
+ case Start() => {
+ for (val t <- tasks) {
+ if (t != this) {
+ t ! p
+// System.out.println("Sending: " + id + "->" + t.id);
+ }
+ }
+// System.out.println("Done sending " + id);
+ }
+ case PingMsg(from) => {
+ pingsExpected = pingsExpected - 1;
+// System.out.println("Rcvd: " + from + "->" + id + " " + pingsExpected);
+ if (pingsExpected == 0) {
+ ctask ! p
+ }
+ }
+ }
+ }
+ }
+}
+
+
+class Collector(n : int) extends Actor {
+ val nTasks = n
+
+ def act(): unit = {
+ for (val i <- 1 to nTasks) {
+ receive {
+ case PingMsg(from) => {
+ //System.out.println("Completed: " + from);
+ }
+ }
+ }
+
+ val elapsed = System.currentTimeMillis() - BigPingPong.beginTime;
+ System.out.println("Elapsed : " + elapsed)
+ System.exit(0);
+ }
+}
12 bench/scala/Msg.scala
@@ -0,0 +1,12 @@
+package examples.actors
+
+abstract class PingMessage
+case class MsgStart() extends PingMessage
+case class MsgPingInit(count: int, pong: Pong) extends PingMessage
+case class MsgSendPing extends PingMessage
+case class MsgPong(sender: Pong) extends PingMessage
+
+abstract class PongMessage
+case class MsgPing(sender: Ping) extends PongMessage
+case class MsgStop() extends PongMessage
+
86 bench/scala/PingPongEx.scala
@@ -0,0 +1,86 @@
+package examples.actors
+
+import scala.actors.Actor
+import scala.actors.Actor._
+
+abstract class PingMessage
+case class MsgStart() extends PingMessage
+case class MsgPingInit(count: int, pong: Pong) extends PingMessage
+case class MsgSendPing extends PingMessage
+case class MsgPong(sender: Pong) extends PingMessage
+
+abstract class PongMessage
+case class MsgPing(sender: Ping) extends PongMessage
+case class MsgStop() extends PongMessage
+
+object PingPongBench {
+ def main(args : Array[String]): Unit = {
+ val ping = new Ping
+ ping.start
+ val pong = new Pong
+ pong.start
+ ping ! MsgPingInit(100000, pong)
+ ping ! MsgStart
+ }
+}
+
+
+class Ping extends Actor {
+ var beginTime: long = 0;
+ def act(): unit = {
+ loop(0, null)
+ }
+ def loop(pingsLeft: int, pong: Pong): unit = {
+ react {
+ case MsgPingInit(count, pong) => {
+ // System.out.println("Ping: Initializing with count:"+count+":"+pong)
+ beginTime = System.currentTimeMillis();
+ loop(count, pong)
+ }
+ case MsgStart() => {
+// System.out.println("Ping: starting.")
+ pong ! MsgPing(this)
+ loop(pingsLeft-1, pong)
+ }
+ case MsgSendPing() => {
+ pong ! MsgPing(this)
+ loop(pingsLeft-1, pong)
+ }
+ case MsgPong(pidS) => {
+// if (pingsLeft % 100 == 0) {
+// System.out.println("Ping: pong from: "+pidS)
+// }
+ if (pingsLeft > 0)
+ this ! MsgSendPing()
+ else {
+// System.out.println("Ping: Stop.")
+ System.out.println("Elapsed: " + (System.currentTimeMillis() - beginTime));
+ pong ! MsgStop()
+ }
+ loop(pingsLeft, pong)
+ }
+ }
+ }
+}
+
+class Pong extends Actor {
+ def act(): unit = {
+ loop(0)
+ }
+
+ def loop(pongCount: int): unit = {
+ react {
+ case MsgPing(pidPing) => {
+// if (pongCount % 100 == 0) {
+// System.out.println("Pong: ping:"+pongCount+" from: "+pidPing)
+// }
+ pidPing ! MsgPong(this)
+ loop(pongCount+1)
+ }
+ case MsgStop() => {
+// System.out.println("Pong: Stop.")
+ System.exit(0)
+ }
+ }
+ }
+}
82 bench/scala/oBigPingPong.scala
@@ -0,0 +1,82 @@
+package examples.actors
+
+/*
+Adapted from PingPongEx.scala, itself an adaption of an example
+from the scala distribution (added timing measurement).
+
+This example creates n tasks and has each send a message to the
+others. It sends the same structure (and number of messages) as the
+kilim/bench/BigPingPong example.
+*/
+import scala.actors._
+import scala.actors.Actor._
+
+object BigPingPong {
+ var beginTime: long = 0
+
+ def main(args : Array[String]): Unit = {
+ val nTasks = Integer.parseInt(args(0))
+ var i = nTasks
+ var tasks: Array[Ping] = new Array[Ping](nTasks)
+ Scheduler.impl = new SingleThreadedScheduler
+ val cTask = new Collector(nTasks);
+ cTask.start()
+
+ beginTime = System.currentTimeMillis()
+ for (val i <- 0 to nTasks-1) {
+ tasks(i) = new Ping(i)
+ }
+ for (val t <- tasks) {
+ t.setOthers(tasks, cTask)
+ t.start();
+ }
+ }
+}
+
+abstract class Msg
+case class PingMsg(from :int ) extends Msg
+
+class Ping(i: int) extends Actor {
+ var id : int = i
+ var tasks: Array[Ping] = Array()
+ var ctask : Collector = null
+
+ def setOthers(others: Array[Ping], ct : Collector) {
+ ctask = ct
+ tasks = others
+ }
+
+ def act(): unit = {
+ System.out.println("" + id + " n = " + tasks.length);
+ for (val t <- tasks) {
+ if (t != this) {
+ t ! new PingMsg(id)
+ receive {
+ case PingMsg(from) => {
+ System.out.println ("" + from + " -> " + id);
+ }
+ }
+ }
+ }
+ ctask ! new PingMsg(id)
+ }
+}
+
+
+class Collector(n : int) extends Actor {
+ val nTasks = n
+
+ def act(): unit = {
+ for (val i <- 1 to nTasks) {
+ receive {
+ case PingMsg(from) => {
+ //System.out.println("Completed: " + from);
+ }
+ }
+ }
+
+ val elapsed = System.currentTimeMillis() - BigPingPong.beginTime;
+ System.out.println("Elapsed : " + elapsed)
+ System.exit(0);
+ }
+}
22 build.sh
@@ -0,0 +1,22 @@
+export CLASSPATH=./classes:./testclasses:./libs/asm-all-2.2.3.jar:./libs/junit.jar:$CLASSPATH
+
+echo making dir: ./classes
+rm -rf ./classes
+rm -rf ./testclasses
+mkdir ./classes
+mkdir ./testclasses
+
+echo Compiling java source ===========================================
+javac -g -d ./classes `find . -name "*.java" `
+
+echo Compiling .j files for testing ==================================
+java -ea kilim.tools.Asm -d ./classes `find . -name "*.j"`
+
+echo Weaving =========================================================
+# Weave all files under ./classes, compiling the tests to
+# ./testclasses while excluding any that match "ExInvalid". These are
+# negative tests for the Weaver.
+java -ea kilim.tools.Weaver -d ./classes -x "ExInvalid|test" ./classes
+java -ea kilim.tools.Weaver -d ./testclasses -x "ExInvalid" ./classes
+
+
146 build.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<project name="kilim" default="all">
+ <path id="kilim.classpath">
+ <pathelement location="classes/" />
+ <fileset dir="./libs">
+ <include name="**/*.jar"/>
+ </fileset>
+ <pathelement path="${java.class.path}" />
+ </path>
+ <path id="kilim.testwovenclasspath">
+ <pathelement location="testclasses/" />
+ <pathelement location="classes/" />
+ <fileset dir="./libs">
+ <include name="**/*.jar"/>
+ </fileset>
+ <pathelement path="${java.class.path}" />
+ </path>
+
+
+ <target name="all" depends="clean,weave" />
+ <target name="test" depends="testnotwoven,testwoven" />
+
+ <target name="compile">
+ <echo message="Compiling src ===================" />
+ <javac debug="on" srcdir="src" destdir="classes"
+ classpathref="kilim.classpath"/>
+ <echo message="Compiling examples ===================" />
+ <javac debug="on" srcdir="examples" destdir="classes"
+ classpathref="kilim.classpath"/>
+ <echo message="Compiling benchmarks ===================" />
+ <javac debug="on" srcdir="bench" destdir="classes"
+ classpathref="kilim.classpath"/>
+ </target>
+
+ <!-- Glob a list of .j files into a space-separated list -->
+ <pathconvert property="dotjfiles" pathsep=" ">
+ <path>
+ <fileset dir="." includes="**/*.j" />
+ </path>
+ </pathconvert>
+
+ <target name="asm" depends="compile">
+ <echo message="Assembling test .j files ===================" />
+ <java classname="kilim.tools.Asm" classpathref="kilim.classpath" fork="yes">
+ <arg line="-d ./classes" />
+ <arg line="${dotjfiles}" />
+ </java>
+ </target>
+
+ <target name="testcompile" depends="asm">
+ <echo message="Compiling test ===================" />
+ <javac debug="on" srcdir="test" destdir="classes"
+ classpathref="kilim.classpath"/>
+ </target>
+
+
+ <target name="weave" depends="testcompile">
+ <echo message="Weaving files ===================" />
+ <java classname="kilim.tools.Weaver" fork ="yes">
+ <classpath refid="kilim.classpath"/>
+ <assertions>
+ <enable/>
+ </assertions>
+ <arg value="-x" />
+ <!-- Skip classes that match ExInvalid. These are negative tests
+ for the weaver. Also skip tests for this pass-->
+ <arg value="ExInvalid|test" />
+ <arg value="-d" />
+ <arg value="./classes" />
+ <arg line="./classes" />
+ </java>
+ <echo message="Weaving test classes ==============" />
+ <java classname="kilim.tools.Weaver" fork ="yes">
+ <classpath refid="kilim.classpath"/>
+ <assertions>
+ <enable/>
+ </assertions>
+ <arg value="-x" />
+ <!-- Weave tests separately into testclasses -->
+ <arg value="ExInvalid" />
+ <arg value="-d" />
+ <arg value="./testclasses" />
+ <arg line="./classes" />
+ </java>
+
+ </target>
+
+ <target name="clean">
+ <echo message="deleting files" />
+ <delete>
+ <fileset defaultexcludes="no" dir="." includes="*~,#*,foo,bar,x,y" />
+ </delete>
+ <delete dir="./classes" />
+ <delete dir="./testclasses" />
+ <mkdir dir="./classes" />
+ <mkdir dir="./testclasses" />
+ </target>
+
+
+ <!-- This runs those tests that do not depend on generated classes
+ present in testclasses. For those, see "testwoven" -->
+ <target name="testnotwoven" >
+ <echo message="Testing =========================" />
+ <java classname="junit.textui.TestRunner" fork="yes">
+ <classpath refid="kilim.classpath"/>
+ <assertions>
+ <enable/>
+ </assertions>
+ <arg value="kilim.test.AllNotWoven" />
+ </java>
+ </target>
+
+ <!-- This runs those tests depend on generated classes in testclasses-->
+ <target name="testwoven" >
+ <echo message="Testing Tasks ======================" />
+ <java classname="junit.textui.TestRunner" fork="yes">
+ <classpath refid="kilim.testwovenclasspath"/>
+ <assertions>
+ <enable/>
+ </assertions>
+ <arg value="kilim.test.AllWoven" />
+ </java>
+ </target>
+
+ <target name="jar" description="generate the distribution">
+ <copy file="License" todir="classes/kilim" />
+ <jar jarfile="kilim.jar" basedir="classes">
+ <zipgroupfileset dir="libs" includes="*.jar">
+ <exclude name="junit.jar" />
+ </zipgroupfileset>
+ <exclude name="kilim/test/**" />
+ <exclude name="kilim/examples/**" />
+ <exclude name="kilim/bench/**" />
+ <manifest>
+ <attribute name="Main-Class" value="kilim.tools.Weaver"/>
+ </manifest>
+ </jar>
+ <jar jarfile="kilim-runtime.jar" basedir="classes">
+ <exclude name="kilim/test/**" />
+ <exclude name="kilim/examples/**" />
+ <exclude name="kilim/bench/**" />
+ <exclude name="kilim/tools/**" />
+ <exclude name="kilim/analysis/**" />
+ </jar>
+ </target>
+</project>
302 docs/IFAQ.txt
@@ -0,0 +1,302 @@
+(Copyright 2007 Sriram Srinivasan)
+
+Kilim IFAQ: Infrequently Asked Questions. Kilim v 0.5
+-- sriram srinivasan (kilim@malhar.net)
+
+
+======================================================================
+Why do people make such a big deal about the how hard it is to do
+thread programming?
+======================================================================
+It is relatively easy to get thread programming correct (to a first
+approximation) by synchronizing all your shared data structures and
+taking locks in the right order. You could have one giant lock and
+just do things one at a time (like the current python interpreter
+with its Global Interpreter Lock).
+
+It is incredibly hard to get multiple threads to work correctly *and*
+to perform efficiently. A lot of painful bugs are created in the
+transition from "get it correct first, then optimize".
+
+======================================================================
+Kilim uses kernel threads. Where do tasks and threads meet?
+======================================================================
+
+Kilim's tasks are cooperatively scheduled and Java threads are
+preemptively scheduled. (I'd prefer kilim's tasks to be preemptable as
+well, but cannot do that without changing the JVM). Tasks are needed
+when you want to split up your workflow into small stages and write
+code as if it is blocking (instead of writing a callback and having to
+jump to that function when it gets called). Tasks should not ideally
+make thread-blocking calls, although if you *have* to call one, it is
+not the end of the world. That's what other threads are for .. they'll
+take care of the other tasks meanwhile.
+
+A Kilim task is owned and managed by a scheduler, which also manages a
+thread pool. When a task needs to block, it removes itself from the
+thread by popping its call stack, remembering enough about each
+activation frame in order to help rebuild the stack and resume, at a
+later point). The scheduler then reuses that thread for some other
+task.
+