Looking at your sample code, I assume that you jump directly to the main method from the command line. This is the worst way you can do micro-profiling in Java!
You must first run your test several times (within the same VM call), at least enough for the JVM to warm up correctly and run for 30 seconds before you even start thinking about starting to measure something - either, This ensures that it will execute compiled (and not interpreted) code and is fully optimized.
You also need to know the cost of running threads. For short cycles, this will be excessively overhead and will consume more time than the cycle itself!
Update
The following definitions follow from ops.scala:
val defaultRunner: FutureTaskRunner = TaskRunners.threadRunner def spawn(p: => Unit)(implicit runner: TaskRunner = defaultRunner): Unit = {...} def replicate(start: Int, end: Int)(p: Int => Unit) {...}
Thus, the actual runner used is entered as implicit, or by default - TaskRunners.threadRunner
You can try changing this to use the thread pool, your code prefix:
implicit val runner = TaskRunners.threadPoolRunner
Or I believe the following will also work:
import concurrent.TaskRunners.threadPoolRunner
Look doesn't matter
Secondly...
I don’t think this parameter will really go through the nested spawn call, it might be better if you just duplicate the method yourself (I currently have a request for this posted on the mailing lists).
For your convenience, here is the method in full, scary, glory:
def replicate(start: Int, end: Int)(p: Int => Unit) { if (start == end) () else if (start + 1 == end) p(start) else { val mid = (start + end) / 2 spawn { replicate(start, mid)(p) } replicate(mid, end)(p) } }
(you still need to define an implicit runner ...)