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