Kotlin子程序是有限状态机和一些任务运行程序(例如,默认的ForkJoinPool)的糖。https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#implementation-详细信息
换句话说,java/kotlin运行时中还没有运行时协程(但这可能会随着http://cr.openjdk.java.net/~rpressler/loom/loom-Proposal.html)。Kotlin协程只是任务的顺序,这些任务是一个接一个执行的。每个任务都可以在线程池中的任何线程中执行。
Go运行时支持"协同程序"。但是goroutines并不是真正的coroutines。Goroutines不允许在程序中设置屈服点。此外,Go不允许设置自定义线程池。您可以只设置默认池中线程的大小。
kotlin协程和goroutines之间的第一个区别是Go运行时管理当前正在运行的协程。当goroutine在某些IO操作(或同步原语)上被阻塞时,Go会选择下一个Job来执行它。在JVM中,没有这样的智能作业切换。
正因为如此,Go可以廉价地更改当前正在运行的作业。Go只需更改少数注册表https://groups.google.com/forum/#!msg/golang nuts/j51G7ieoKh4/wxNaKkFEfvcJ。但有些人说,JVM可以使用线程堆栈,而不是使用寄存器。因此根本没有保存和加载寄存器。
kotlin协程和goroutines之间的第二个区别是协程的类型。Kotlin协程是无堆栈的协程。Goroutines是堆叠的coroutines。Kotlin协程的所有状态都存储在Kotlin上下文中,该上下文存储在堆中。Goroutines状态存储在寄存器和线程堆栈中。
我想知道,哪些协同程序(goroutines和kotlin协同程序)在IO绑定任务中更快?CPU限制的任务?内存消耗情况如何?
一般来说,很难提前判断哪一个能更好地解决你手头的问题。你必须为你的特定工作负载运行基准测试才能弄清楚。然而,这里有一个关键差异的概括,应该会给你一些指导。
Kotlin协程每个简单实例所需的内存少于Go协程。Kotlin中的一个简单协程只占用几十个字节的堆内存,而Go协程则以4KiB的堆栈空间开始。这意味着,如果你计划进行数百万次的协同活动,那么在科特林的协同活动可能会让你在围棋比赛中占据优势。它还使Kotlin协同程序更适合于非常短命和小的任务,如生成器和懒惰序列。
Kotlin协程可以到达任何堆栈深度,但每次调用挂起函数都会为其堆栈分配堆中的对象。Kotlin协程中的调用堆栈目前被实现为堆对象的链表。相比之下,Go中的goroutine使用线性堆栈空间。这使得围棋中在深栈上的悬挂更加有效。因此,如果您正在编写的代码在堆栈的深处挂起,您可能会发现goroutine对您来说更高效。
高效异步IO是一个非常多维的设计问题。对于一种应用程序有效的方法可能不会为另一种应用提供最佳性能。Kotlin协程中的所有IO操作都是由用Kotlin或Java编写的库实现的。Kotlin代码可以使用各种各样的IO库。In Go异步IO由Go运行时使用通用Go代码不可用的原语来实现。如果实现IO操作的Go方法非常适合您的应用程序,那么您可能会发现它与Go运行时的紧密集成为您带来了优势。另一方面,在Kotlin中,您可以找到一个库或自己编写一个库,以最适合您的应用程序的方式实现异步IO。
Go运行时完全控制调度goroutines在物理操作系统线程上的执行。这种方法的优点是你不必考虑所有的问题。使用Kotlin协程,您可以对协程的执行环境进行细粒度控制。这很容易出错(例如,您可能只是创建了太多不同的线程池,并将CPU时间浪费在它们之间的上下文切换上)。然而,它使您能够为应用程序微调线程分配和上下文切换。例如,在Kotlin中,很容易在单个操作系统线程(或线程池)中执行整个应用程序或其代码的子集,只需为此编写适当的代码就可以完全避免在操作系统线程之间切换上下文。