调用约定和上下文切换
💡
原文中文,约1400字,阅读约需4分钟。
📝
内容提要
在编写协程库时,上下文切换速度受调用约定的影响。采用“preserve_none”调用约定可以减少寄存器保留,从而提高切换效率。通过感知上下文,系统能够自动决定切换的工作量,降低开销。
🎯
关键要点
- 上下文切换速度受调用约定影响很大。
- 用户协程的上下文切换本质上是调用一个函数,需要切换非易失性寄存器。
- 非易失性寄存器越多,上下文切换时需要保留和恢复的寄存器数量越多。
- 内核进行上下文切换时,所有寄存器都需保留,开销最大。
- 使用内联汇编的 clobbered registers 列表可以自动生成寄存器的保存和恢复代码。
- preserve_none 调用约定下,尽可能不保留寄存器,全是易失性寄存器。
- 使用 preserve_none 调用约定实现 zcontext_swap 时,只需切换 rsp 寄存器。
- 在无 hook 的情况下,只需 8 条指令完成上下文切换,效率极高。
- 调用 zcontext_swap 的地方仍需保持寄存器,工作量没有减少。
- 在某些情况下,调用方的寄存器不需要保留那么多,可以减少 CPU 开销。
- 保留多少寄存器取决于协程调度的上下文环境。
- 通过感知上下文自动决定切换的工作量,可以使协程上下文切换的开销与无栈协程一样小。
➡️