Go和Kotlin/Native协程对比

本文对比了Kotlin Native和Go在单核和多核环境下的协程性能,发现Kotlin Native的协程调度和运算速度较快,但Go在编译速度上有优势。在多线程场景下,Kotlin jvm协程仍优于Go,且Kotlin的并发模型和生态系统更丰富。因此,对于需要原生并发编程和小工具开发的场景,Kotlin可能成为更好的选择。

说明

系统说明
  • Kotlin版本:1.4.10
  • Golang版本:1.12.9
  • OS:Windows
  • CPU:4核8线程 3.6GHz
  • 内存:32G
其他说明
  • 由于Kotlin Native的协程默认只支持单线程,因此限制Goroutines也只使用单核
  • 测试1为了公平Kotlin不在jvm上跑,Kotlin和Go均编译为exe可执行文件
  • 测试2会对比Kotlin在jvm多线程和不限制Goroutines的对比,这是最常用的开发场景
  • 但由于主力服务端还是Linux,后期也许会增加在Linux系统上的对比结果
Kotlin Native gradle文件
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.4.10'
}
group = 'me.10221903'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}
kotlin {
    def hostOs = System.getProperty("os.name")
    def isMingwX64 = hostOs.startsWith("Windows")
    KotlinNativeTargetWithTests nativeTarget
    if (hostOs == "Mac OS X") nativeTarget = macosX64('native')
    else if (hostOs == "Linux") nativeTarget = linuxX64("native")
    else if (isMingwX64) nativeTarget = mingwX64("native")
    else throw new GradleException("Host OS is not supported in Kotlin/Native.")

    nativeTarget.with {
        binaries {
            executable {
                entryPoint = 'main'
            }
        }
    }
    sourceSets {
        nativeMain {
            dependencies {
                // implementation "com.autodesk:coroutineworker:0.6.2"
                implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9-native-mt"
            }
        }
        nativeTest {

        }
    }
}

测试1:原生单核协程对比

package main

import (
	"fmt"
	"sync"
	"time"
)

func fib(n int) int {
	if n <= 1 {
		return n
	}
	return fib(n-1) + fib(n-2)
}

func massiveRun(action func()) {
	n := 100 // 可修改参数
	k := 1000
	t0 := time.Now()
	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func() {
			for j := 0; j < k; j++ {
				action()
			}
			wg.Done()
		}()
	}
	wg.Wait()
	elapsed := time.Since(t0)
	fmt.Println("Completed 100000 actions in ", elapsed)
}

func main() {
	runtime.GOMAXPROCS(1)
	massiveRun(func() {
		fib(20) // 可修改参数
	})
}

Kotlin测试代码

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis

fun fib(n: Int): Int {
    if (n <= 1){
        return n
    }
    return fib(n-1) + fib(n-2)
}

suspend fun massiveRun(action: suspend () -> Unit) {
    val n = 100  // 启动的协程数量
    val k = 1000 // 每个协程重复执行同一动作的次数
    val time = measureTimeMillis {
        coroutineScope { // 协程的作用域
            repeat(n) {
                launch {
                    repeat(k) { action() }
                }
            }
        }
    }
    println("Completed ${n * k} actions in $time ms")
}


fun main() = runBlocking {
    withContext(Dispatchers.Default) {
        massiveRun {
            fib(20)
        }
    }
}
语言n = 100, fib(20)n = 100, fib(25)n = 1000, fib(20)
go5.24s57.1s49s
kotlin3.3s38.3s35s
结论
  1. Kotlin Native的协程调度和运算比goroutine快40 - 60%
  2. 但是编译到原生的速度,Go吊打Kotlin
  3. 其他暂未对比,可见Kotlin确实是一个很牛的语言

测试2:jvm多核 vs Go多核

TODO
在这里插入图片描述

语言n = 100, fib(20)n = 100, fib(25)n = 1000, fib(20)
go0.98s10.86s9.76s
kotlin0.73s7.5s7.3s
结论
  1. 两者对多线程的协程支持都很不错
  2. Kotlin jvm的协程调度和运算比goroutine快33-45%,幅度变小,但go依旧被吊打
  3. 放开所有限制跑,Kotlin的协程还是比goroutine好很多,加上Java生态好于Go,Kotlin的特性也比Go好很多,Kotlin也支持Channel和Select这种并发模型,所有最终结论,Kotlin获胜。

结语

  1. 在一些企业场景中,经常需要开发些小工具给业务人员使用,装个jvm或者打包整个Python环境给对方显然是一种很难的做法。因此在一些计算密集场景下,必然有以下需求:简单易用的并发编程模型,能尽量小的编译为二进制文件(EXE),运行速度快等。
  2. 首先排除C/C++,对主力为Java的程序员来说学习成本太高,收益太低。剩下支持原生的就只剩下Go和Kotlin了,Go有杀手级生态Docker和K8S等,Kotlin寄托于Java生态,在绝大多数场景下Kotlin还是好于Go,但令我没想到的是,居然在协程的支持上,Go居然也输了。
  3. 尽管现在Go在服务端开发上还是比Kotlin更常用,一些大公司也用Go做后端开发,而Kotlin主力还是在于Android开发,尽管Spring对Kotlin也有很好的支持,但是暂时没见到Kotlin的后端使用
  4. 后期我这里的后端语言也会慢慢转向Kotlin
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值