调用约定和上下文切换
内容提要
在编写协程库时,上下文切换速度受调用约定的影响。采用“preserve_none”调用约定可以减少寄存器保留,从而提高切换效率。通过感知上下文,系统能够自动决定切换的工作量,降低开销。
关键要点
-
上下文切换速度受调用约定影响很大。
-
用户协程的上下文切换本质上是调用一个函数,需要切换非易失性寄存器。
-
非易失性寄存器越多,上下文切换时需要保留和恢复的寄存器数量越多。
-
内核进行上下文切换时,所有寄存器都需保留,开销最大。
-
使用内联汇编的 clobbered registers 列表可以自动生成寄存器的保存和恢复代码。
-
preserve_none 调用约定下,尽可能不保留寄存器,全是易失性寄存器。
-
使用 preserve_none 调用约定实现 zcontext_swap 时,只需切换 rsp 寄存器。
-
在无 hook 的情况下,只需 8 条指令完成上下文切换,效率极高。
-
调用 zcontext_swap 的地方仍需保持寄存器,工作量没有减少。
-
在某些情况下,调用方的寄存器不需要保留那么多,可以减少 CPU 开销。
-
保留多少寄存器取决于协程调度的上下文环境。
-
通过感知上下文自动决定切换的工作量,可以使协程上下文切换的开销与无栈协程一样小。
延伸解读
调用约定的重要性
调用约定在协程上下文切换中扮演着关键角色。选择合适的调用约定,如preserve_none,可以显著减少需要保留的寄存器数量,从而提高切换效率。这一选择直接影响到系统性能,尤其是在高并发场景下,合理的调用约定能够降低CPU负担。
上下文感知的优势
通过上下文感知,系统能够智能决定在协程切换时需要保留的寄存器数量。这种动态调整不仅优化了性能,还能在特定情况下减少不必要的开销,使得协程的上下文切换效率接近无栈协程的水平。开发者在设计协程库时应重视这一特性。
内核与用户协程的对比
内核进行上下文切换时需要保留所有寄存器,导致开销较大。而用户协程通过使用preserve_none调用约定,可以减少保留寄存器的数量,从而实现更快的切换。这一对比强调了在协程设计中选择合适的上下文切换策略的重要性。
延伸问答
上下文切换的速度受什么影响?
上下文切换的速度受调用约定的影响很大。
什么是preserve_none调用约定?
preserve_none调用约定是指尽可能不保留寄存器,使用全易失性寄存器。
使用preserve_none调用约定的优势是什么?
使用preserve_none调用约定可以减少寄存器保留,从而提高上下文切换效率。
上下文切换时需要保留哪些寄存器?
上下文切换时需要保留非易失性寄存器,数量取决于调用约定。
如何实现高效的上下文切换?
通过使用preserve_none调用约定和感知上下文,可以实现高效的上下文切换。
上下文感知协程切换的意义是什么?
上下文感知协程切换可以自动决定切换的工作量,从而降低开销。