I have written 3 simple programs to test coroutines performance advantage over threads. Each program does a lot of common simple computations. All programs were run separately from each other. Besides execution time I measured CPU usage via Visual VM
IDE plugin.
First program does all computations using
1000-threaded
pool. This piece of code shows the worst results (64326 ms
) comparing to others because of frequent context changes:val executor = Executors.newFixedThreadPool(1000) time = generateSequence { measureTimeMillis { val comps = mutableListOf<Future<Int>>() for (i in 1..1_000_000) { comps += executor.submit<Int> { computation2(); 15 } } comps.map { it.get() }.sum() } }.take(100).sum() println("Completed in $time ms") executor.shutdownNow()
Second program has the same logic but instead of
1000-threaded
pool it uses onlyn-threaded
pool (wheren
equals to amount of the machine's cores). It shows much better results (43939 ms
) and uses less threads which is good too.val executor2 = Executors.newFixedThreadPool(4) time = generateSequence { measureTimeMillis { val comps = mutableListOf<Future<Int>>() for (i in 1..1_000_000) { comps += executor2.submit<Int> { computation2(); 15 } } comps.map { it.get() }.sum() } }.take(100).sum() println("Completed in $time ms") executor2.shutdownNow()
Third program is written with coroutines and shows a big variance in the results (from
41784 ms
to81101 ms
). I am very confused and don't quite understand why they are so different and why coroutines sometimes slower than threads (considering small async calculations is a forte of coroutines). Here is the code:time = generateSequence { runBlocking { measureTimeMillis { val comps = mutableListOf<Deferred<Int>>() for (i in 1..1_000_000) { comps += async { computation2(); 15 } } comps.map { it.await() }.sum() } } }.take(100).sum() println("Completed in $time ms")
I actually read a lot about these coroutines and how they are implemented in kotlin, but in practice I don't see them working as intended. Am I doing my benchmarking wrong? Or maybe I'm using coroutines wrong?