简体   繁体   English

为什么 Kotlin 协程需要更长的时间

[英]Why Kotlin Coroutine is taking longer time

I have two programs我有两个程序

  1. with coroutine与协程

I have 3 loops and i tried assigning each loop to a coroutine for quick execution.我有 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)
}

Output 109 Output 109

  1. Without Coroutine没有协程
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)
}

Output 9 Output 9

I have used timer to calculate the exectution time, but the coroutine code is taking longer.我已经使用计时器来计算执行时间,但是协程代码需要更长的时间。

Why is it working like this, how can i make the coroutine part faster?为什么它会这样工作,我怎样才能让协程部分更快?

Your code disregards a great deal of concerns that make your two examples very different.您的代码忽略了许多使您的两个示例非常不同的问题。

First of all, you should never trust the timing of the very first run through the code.首先,你永远不应该相信第一次运行代码的时间。 This is the time when all the heavyweight class initialization happens, including the initialization of the classes you touch indirectly by calling a library function.这是所有重量级 class 初始化发生的时间,包括您通过调用库 function 间接接触的类的初始化。

Second, you also ignore all the optimizations the JIT compiler does to the bytecode.其次,您还忽略了 JIT 编译器对字节码所做的所有优化。 Most important in your case is that the code does nothing but increment local variables without using them afterwards.在您的情况下,最重要的是代码除了增加局部变量而不在之后使用它们之外什么都不做。 The JIT compiler will be happy to entirely delete your loops. JIT 编译器很乐意完全删除您的循环。 Even if you use the results afterwards, the compiler may be able to do some simple reasoning on what the resulting value will be after 1,000,000 increments.即使您之后使用结果,编译器也可以对 1,000,000 次增量后的结果值进行一些简单的推理。

Your first example, with coroutines, is fundamentally different in that it submits tasks to the commonPool executor service.您的第一个示例,使用协程,根本不同,因为它将任务提交给commonPool执行器服务。 This means your incrementing code happens within a lambda that captures your local variable.这意味着您的递增代码发生在捕获局部变量的 lambda 中。 In order to make it work, the compiler must transform it into an instance variable attached to the lambda.为了使其工作,编译器必须将其转换为附加到 lambda 的实例变量。 This muddies the waters in terms of the compiler proving the loop can be safely eliminated.就编译器而言,这使水变得混乱,证明可以安全地消除循环。

However, even if you accounted for all these things, your code is broken in an elementary way as well: you don't await for the completion of the launched coroutines.然而,即使你考虑了所有这些事情,你的代码也会以一种基本的方式被破坏:你不会等待启动的协程完成。 So after you fix the above issues and make the loops do some non-trivial work whose results you actually check for, you'll find that the coroutine examples report constant time that doesn't depend on the number of loop iterations.因此,在您解决上述问题并使循环执行一些您实际检查其结果的重要工作之后,您会发现协程示例报告的恒定时间不依赖于循环迭代的次数。

I think what best explains your current results is the initialization costs.我认为最能解释您当前结果的是初始化成本。 Just put a big outer loop over the whole code and the coroutine example will appear to perform much better than now.只需在整个代码上放置一个大的外循环,协程示例的性能就会比现在好得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM