簡體   English   中英

為什么 Kotlin 協程需要更長的時間

[英]Why Kotlin Coroutine is taking longer time

我有兩個程序

  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)
}

Output 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)
}

Output 9

我已經使用計時器來計算執行時間,但是協程代碼需要更長的時間。

為什么它會這樣工作,我怎樣才能讓協程部分更快?

您的代碼忽略了許多使您的兩個示例非常不同的問題。

首先,你永遠不應該相信第一次運行代碼的時間。 這是所有重量級 class 初始化發生的時間,包括您通過調用庫 function 間接接觸的類的初始化。

其次,您還忽略了 JIT 編譯器對字節碼所做的所有優化。 在您的情況下,最重要的是代碼除了增加局部變量而不在之后使用它們之外什么都不做。 JIT 編譯器很樂意完全刪除您的循環。 即使您之后使用結果,編譯器也可以對 1,000,000 次增量后的結果值進行一些簡單的推理。

您的第一個示例,使用協程,根本不同,因為它將任務提交給commonPool執行器服務。 這意味着您的遞增代碼發生在捕獲局部變量的 lambda 中。 為了使其工作,編譯器必須將其轉換為附加到 lambda 的實例變量。 就編譯器而言,這使水變得混亂,證明可以安全地消除循環。

然而,即使你考慮了所有這些事情,你的代碼也會以一種基本的方式被破壞:你不會等待啟動的協程完成。 因此,在您解決上述問題並使循環執行一些您實際檢查其結果的重要工作之后,您會發現協程示例報告的恆定時間不依賴於循環迭代的次數。

我認為最能解釋您當前結果的是初始化成本。 只需在整個代碼上放置一個大的外循環,協程示例的性能就會比現在好得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM