忘川彼岸|Go:Goroutine 的切换过程实际上涉及了什么( 二 )


堆栈在被阻塞之前 , 正在运行的 Goroutine 具有其原始堆栈 , 该堆栈包含临时存储器 , 例如变量 i :
忘川彼岸|Go:Goroutine 的切换过程实际上涉及了什么然后 , 当它在通道上阻塞时 , goroutine 将切换到 g0 及其堆栈(更大的堆栈):
忘川彼岸|Go:Goroutine 的切换过程实际上涉及了什么在切换之前 , 堆栈将被保存 , 以便在 Goroutine 再次运行时进行恢复:
忘川彼岸|Go:Goroutine 的切换过程实际上涉及了什么现在 , 我们对 Goroutine 切换中涉及的不同操作有了一个完整的了解 , 让我们继续看看它是如何影响性能的 。
我们应该注意 , 诸如 arm 等 CPU 架构需要再保存一个寄存器 , 即 LR 链接寄存器 。
性能我们仍然使用上述的程序来测量一次切换所需的时间 。 但是 , 由于切换时间取决于寻找下一个要调度的 Goroutine 所花费的时间 , 因此无法提供完美的性能视图 。 在函数调用情况下进行的切换要比阻塞在通道上的切换执行更多的操作 , 这也会影响到性能 。
让我们总结一下我们将要测量的操作:

  • 当前 g 阻塞在通道上并切换到 g0 :PC g0 g0
  • g0 寻找新的 Goroutine 来运行;
  • g0 使用所选的 Goroutine 进行切换:PC PC
结果如下:
忘川彼岸|Go:Goroutine 的切换过程实际上涉及了什么从 g 到 g0 或从 g0 到 g 的切换是相当迅速的 , 它们只包含少量固定的指令 。 相反 , 对于调度阶段 , 调度程序需要检查许多资源以便确定下一个要运行的 goroutine , 根据程序的不同 , 此阶段可能会花费更多的时间 。
【忘川彼岸|Go:Goroutine 的切换过程实际上涉及了什么】该基准测试给出了性能的数量级估计 , 由于没有标准的工具可以衡量它 , 所以我们并不能完全依赖于这个结果 。 此外 , 性能也取决于 CPU 架构、机器(本文使用的机器是 Mac 2.9 GHz 双核 Intel Core i5)以及正在运行的程序 。


推荐阅读