Go Goroutine、Java 19 虚拟线程与Kotlin 协程的性能比较 - RobertDeng


本文试图比较示例逻辑在不同流行语言(Go、Java 和 Kotlin)下运行时的不同虚拟线程运行性能。

与传统的线程技术相比,虚拟线程减少了从用户空间到内核空间的切换时间成本,从而在多线程应用程序开发中提供了更好的性能。

结论:Go(Goroutine) 的性能比 Java(jdk19 虚拟线程) 和 Kotlin(Coroutines) 要好得多,它可能受益于 Go 有更多的编译时间优化,并且它比 JVM 中的 Java/Kotlin 成本更低。

第一个测试是使用 Kotlin 版本 1.7.20 运行一个简单的 1,000,000 次迭代,使用协程大约需要 2 毫秒。

package com.test

import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.launch

fun main() = runBlocking { // this: CoroutineScope
    launch { 
      
        val start = System.nanoTime()
        for (i in 1..1_000_000) {
        }
        println(
"elapsd time :" + (System.nanoTime() - start) /  1_000 / 1_000 + " ms")
    }
    println(
"Programme End"
}

第二个测试是运行一个简单的 1,000,000 次迭代,使用 Go 版本 1.19.2,它使用 goroutines 花费了大约 700 微秒。

package main

import (
    "log"
   
"os"
   
"sync"
   
"time"
)


func main() {
        logger := log.New(os.Stdout,
"", 0)

       
// Sync between goroutines.
        var wg sync.WaitGroup

        wg.Add(1)
        go func() {
          defer wg.Done()
          start := time.Now()
          for i := 0; i < 1_000_000; i++ {
          }
          duration := time.Since(start)
          logger.Print(
"one million times loop use time:")
          logger.Println(duration);
          logger.Println(
"Programme End")
        }()

       
// Wait all goroutines.
        wg.Wait()
}

第三个测试是运行一个简单的 1,000,000 次迭代,使用采用 open jdk 19,使用协程大约需要 4 毫秒。

package com.test;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;

public class PerformanceTest {

        public static void main(String[] args) {
                // TODO Auto-generated method stub
      Instant start = Instant.now();

      try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        for(int i = 0; i < 1_000_000; i++) {
        }
        Instant finish = Instant.now();

        long timeElapsed = Duration.between(start, finish).toMillis();
        System.out.println(
"Total elapsed time : " + timeElapsed + " ms");
        System.out.print(
"Programme End");
      }



        }

}