一个goroutine/coroutine什么时候切换到另一个coroutine/goroutine?

问题描述 投票:0回答:1

我有一个程序,我在其中测量 goroutine 完成任意任务所需的时间,在本例中为合并排序。我在 Kotlin 和 Go 中创建了完全相同的程序(据我所知),以模糊地比较 Goroutines 和协程。

在我的机器上,Kotlin 程序在大约 15 秒内完成,Go 程序在大约一分钟内完成,因此我预计每个 goroutine 大约慢 4 倍。然而,根据 Kotlin 的说法,每个协程大约需要 3 毫秒。每个 goroutine 大约需要 25 秒,这显然比 3 毫秒慢得多。 我认为这可能是由于 Go 切换 goroutines 造成的,因此每个 goroutine 平均需要很长时间,因为它们都是“并行”处理的,无论我的机器有多少核。然而,在 Kotlin 中,似乎只有与机器拥有的内核一样多的协程才会同时运行,因此协程运行的平均时间要低得多。任何人都可以确认吗?两个程序都在对相同的数据进行排序。

如果有人感兴趣,链接代码,减去合并排序部分,以及获取数据的部分与讨论不太相关。 https://gist.github.com/danielschutt/80a97ec56090b0d51e306c4558963555

我预计协程和 goroutine 花费的时间差不多。

kotlin go coroutine goroutine context-switch
1个回答
0
投票

我对 go 知之甚少,但在 Kotlin 中,协程只有在协程执行某些操作时才会被挂起(例如调用另一个挂起函数,调用

dalay
等)。否则协程将运行直到它完成执行。

在您分享的示例中,每个 kotlin corroutine 一次完成整个数组的排序,在它终止后,加载下一个 coroutine 并重复该过程。这也使它运行得更快,因为没有协程上下文的安装/卸载(我希望我在这里记得正确的术语!)。该示例使用默认调度程序,它具有与 CPU 核心一样多的线程(并且它是用于 CPU 密集型操作的正确线程)。如果您使用 IO 调度程序,它会运行得更慢,因为 kotlin 将启动 64 个线程,并且这些线程将竞争获取 CPU 时间并使用一些 CPU 时间进行上下文切换。

做一些研究我发现差异(在某种程度上如上所述)是由于调度。

  • Kotlin 使用 cooperative scheduler,协程负责自己暂停。
  • Go 使用 抢占式调度程序,因此它可以在多个点暂停协程并调度不同的协程。

正如您所提到的,go 启动所有协程,它们一起进步。

© www.soinside.com 2019 - 2024. All rights reserved.