【问题标题】:Why Kotlin Coroutine is taking longer time为什么 Kotlin 协程需要更长的时间
【发布时间】:2021-03-12 07:02:18
【问题描述】:

我有两个程序

  1. 使用协程

我有 3 个循环,我尝试将每个循环分配给一个协程以便快速执行。

import kotlinx.coroutines.*
fun main() {
    val time = measureTimeMillis() {
    var i=0
    var j=0
    var k=0
    GlobalScope.launch(Dispatchers.Default){     
     while(i<1000000)
           i++ }
    GlobalScope.launch(Dispatchers.Default){     
     while(j<1000000)
           j++}
    GlobalScope.launch(Dispatchers.Default){     
     while(k<1000000)
           k++}
      
    }    
    println(time)
}

输出 109

  1. 没有协程
import kotlin.system.measureTimeMillis
import kotlinx.coroutines.*

fun main() {
    val time = measureTimeMillis() {
    var i=0  
    var j=0
    var k=0
          while(i<1000000)
            i++
        while(j<1000000)
            j++
        while(k<1000000)
            k++
              
    }    
    println(time)
}

输出 9

我已经使用定时器来计算执行时间,但是协程代码需要更长的时间。

为什么会这样,我怎样才能让协程部分更快?

【问题讨论】:

    标签: kotlin kotlin-coroutines coroutine


    【解决方案1】:

    您的代码忽略了许多使您的两个示例非常不同的问题。

    首先,您永远不应该相信第一次运行代码的时间。这是所有重量级类初始化发生的时间,包括您通过调用库函数间接接触到的类的初始化。

    其次,您还忽略了 JIT 编译器对字节码所做的所有优化。在您的情况下,最重要的是代码除了增加局部变量而不在之后使用它们之外什么都不做。 JIT 编译器很乐意完全删除您的循环。即使您之后使用结果,编译器也可以对 1,000,000 次增量后的结果值进行一些简单的推理。

    您的第一个示例,使用协程,根本不同,它将任务提交给commonPool 执行器服务。这意味着您的递增代码发生在捕获局部变量的 lambda 中。为了使其工作,编译器必须将其转换为附加到 lambda 的实例变量。这在编译器证明循环可以被安全消除方面混淆了。

    但是,即使您考虑了所有这些事情,您的代码也会以一种基本的方式被破坏:您不会等待已启动的协程完成。因此,在您解决上述问题并让循环执行一些您实际检查其结果的重要工作后,您会发现协程示例报告的恒定时间不依赖于循环迭代的次数。

    我认为最能解释您当前结果的是初始化成本。只需在整个代码上放置一个大的外循环,协程示例的性能就会比现在好得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 2011-11-09
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      相关资源
      最近更新 更多