为何100个协程简单迭代时Dispatchers.Default比Dispatchers.IO更快?
我为探究使用Dispatchers.IO替代Dispatchers.Default的差异,编写了如下代码:
runBlocking { val list = mutableListOf<Job>() val time1 = System.currentTimeMillis() for (i in 1..100){ val job = lifecycleScope.launch(Dispatchers.IO) { val c = "c$i" Log.i("CoroutineRunnerLog", "Launched a coroutine $c on Thread : ${Thread.currentThread().name}") for (j in 1..10){ Log.d("CoroutineRunnerLog", "Coroutine $c, j = $j, Thread : ${Thread.currentThread().name}") } } list.add(job) } list.joinAll() val time2 = System.currentTimeMillis() Log.e("CoroutineRunnerLog", "difference is = ${time2 - time1}") }
已知Dispatchers.IO线程池最大可扩展至64个线程,而Dispatchers.Default的最大线程数等于CPU核心数(我的设备为8核)。我原本预期Dispatchers.IO性能更优,但实际测试结果显示:
Output : Dispatchers.IO = 200 - 300 ms Dispatchers.Default = 80 - 100 ms
我想了解为何线程数更少的Dispatchers.Default反而比Dispatchers.IO运行更快。
任务类型与调度器定位不匹配:你的测试任务属于CPU密集型任务(循环执行日志打印,核心是字符串格式化、日志缓冲区写入等CPU操作)。
Dispatchers.Default正是为CPU密集型场景设计的,线程数等于CPU核心数,能让每个核心持续处理任务,避免线程竞争;而Dispatchers.IO是为IO密集型任务(如网络请求、文件读写)设计的,这类任务大部分时间处于等待IO响应的状态,需要更多线程来利用空闲时间,但CPU密集型任务用多线程只会增加负担。线程上下文切换开销:当线程数量超过CPU核心数时,操作系统需要频繁切换线程上下文——保存当前线程的状态、加载下一个线程的状态,这个过程会消耗额外的CPU资源。你的测试中
Dispatchers.IO最多会启动64个线程,远多于8核CPU的处理能力,大量的上下文切换直接拉高了总耗时;而Dispatchers.Default的8个线程刚好匹配核心数,每个线程能持续占用CPU,几乎没有上下文切换的额外开销。日志操作的本质:虽然日志看起来是IO操作,但Android的Log系统经过了优化,实际执行时更多是CPU层面的处理(字符串拼接、缓冲区同步等),并非典型的阻塞IO任务,因此更适合
Dispatchers.Default这类针对CPU密集场景优化的调度器。
内容的提问来源于stack exchange,提问作者Roop Kishore

