Solution: Experiments with dispatchers
On my machine (MacBook M2 Pro 2022), the results are as follows:
Dispatcher | CPU-intensive | Blocking | Suspending |
---|---|---|---|
1 thread | 21 794 ms | 100 450 ms | 1 030 ms |
Dispatchers.Default | 3 066 ms | 10 058 ms | 1 024 ms |
Dispatchers.IO | 2 973 ms | 2 025 ms | 1 025 ms |
100 threads | 3 038 ms | 1 023 ms | 1 024 ms |
Let's discuss these results. Starting from CPU-intensive, it should be clear that 1 thread is the worst choice because it does not use the power of all 10 cores in my machine. All the other dispatchers tested here have similar execution times. In theory, Dispatchers.Default
should be fastest because it avoids the costs of additional threads; however, when I was running this experiment, there were many other processes running on my machine (IntelliJ, Chrome), and dispatchers with more threads were able to access the CPU more frequently.
For blocking operations, the more threads a dispatcher has, the less time it takes to execute. The formula is linear: the number of coroutines divided by the number of threads, rounded up. However, you need to remember that the more threads you have, the more memory you use, and the more context switches you have; so, you should not use too many threads.
Regarding suspending functions, the dispatcher does not matter because suspending functions do not block threads. So, if we only suspend and do nothing blocking or CPU-intensive, then the dispatcher does not matter.