https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-goroutine/#65-%E8%B0%83%E5%BA%A6%E5%99%A8
https://hitzhangjie.gitbook.io/libmill/basics/context-switching-cost#liang-hua-shang-xia-wen-qie-huan-kai-xiao
上下文切换,主要就是任务切换时任务状态的保存,以及选择下一个待执行的任务并将其上下文恢复。这其中的开销,主要包含这么几部分:
切换直接引入的开销
这部分是比较好理解的,保存、恢复上下文时需要保存的寄存器的数据量,直接决定了这部分开销。有些寄存器对上下文切换开销影响是比较大的,比如FPU、MMX、SSE、AVX等寄存器的状态,由于其数据量是比较大的,可能会增加几KB的数据,特别是AVX寄存器,AVX2有512字节,AVX-512有2KB,这么大的数据量在上下文切换时还需要读写内存,这里的内存读写延迟(+读写寄存器)引入的开销是比较大的。
切换间接引入的开销
间接引入的开销,主要是与cache miss相关的,CPU本身有自己的L1、L2、L3级缓存,对于页式管理还有TLB(转换旁路缓冲),还有分支预测相关的(branch direction, branch target, return buffer),等等
L1~L3 cache miss
TLB cache miss
协程相对进程、线程会更加轻量,包括其初始栈内存大小、上下文信息、创建销毁速度,等等。那不禁要问,协程的上下文是长什么样子,和进程、线程有什么差别呢?
以go语言为例,goroutine上下文切换的成本很低,goroutine上下文切换仅涉及三个寄存器(PC、SP、DX)的修改,那线程呢?线程的上下文切换需要包括模式切换(从用户模式切换到内核模式) 和PC、SP等16个寄存器的修改。开销谁大谁小一看便知。
https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/edit#heading=h.c3s328639mw9