katsusan / gowiki

0 stars 0 forks source link

Go scheduling #1

Open katsusan opened 4 years ago

katsusan commented 4 years ago

refer: https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html

  1. OS scheduler 线程状态:

    • Waiting:network/disk IO等待,系统调用,以及同步操作
    • Runnable:已经具备执行条件的任务,只等分配时间片
    • Executing:正在执行中的任务

    按照资源消耗类型可以将任务分为CPU密集型和IO密集型。 上下文切换: 当前主流操作系统Linux/MacOS/Windows都是抢占式调度,这使得线程的执行变得不可预测。 上下文切换的代价非常高昂,根据影响因素不同大概花费1000-1500ns, 按照 3GHz with 4 instructions per cycle=12instructions/ns的标准浪费了12K-18K的指令执行。 如果你的程序主要是IO密集型,由于阻塞时本来就要将状态从Executing切换为Waiting, 此时需要移交CPU控制权因此上下文切换是必须的,并不会造成很大困扰。 而如果你的程序是CPU密集型,频繁的上下文切换浪费了很多CPU时间片,真正有效的执行 时间很少,因此性能会表现的很糟糕。

    linux中的进程上下文切换: (1) suspending the progression of one process and storing the CPU's state (i.e., the context) for that process somewhere in memory (2) retrieving the context of the next process from memory and restoring it in the CPU's registers (3) returning to the location indicated by the program counter (i.e., returning to the line of code at which the process was interrupted) in order to resume the process

    CPU Cache: 从主存直接读取数据要耗费100~300个时钟周期,由于是按顺序执行指令,这样的延迟是 不可接受的,因此引入了CPU缓存这一概念,目前的intel架构里L1和L2为每个核独占,L3 为多核共享,其中L1还分为指令缓存L1 Instruction和数据缓存L1 Data。

    I7-8770K(6核)为例,L1为384KB(32KB Instruction+32KB Data per core),L2为256KB per core, L3为6核共享12MB,至于L1、L2、L3的速度各代处理器略有不同,大概的数据如下:

    • L1的存取:4个时钟周期
    • L2的存取:11个时钟周期
    • L3的存取:39个时钟周期
    • RAM的存取:107个时钟周期
  2. Go Scheduler Go1.14以前(1.2-1.13),实行基于协作的抢占式调度,在以下几种情形可能会发生执行权的变更:

    • The use of the keyword go
    • Garbage collection
    • System calls
    • Synchronization and Orchestration

    到了Go1.14,引入了基于SIGURG信号的抢占式调度,思想就是在进程启动时注册一个SIGURG的 信号处理函数runtime.doSigPreempt,支持向线程发送SIGURG信号,doSigPreempt会在收到信号 SIGURG时判断是否是抢占的safe point,是的话则修改信号handler中的ucontext(见sigaction),
    执行asyncPreempt的指令。

    基于信号的抢占式调度同时也使得GC时的STW更方便,只需要向执行中的M发送SIGURG信号则 所有运行中的goroutine都会在safe point暂停等待GC重新start the world。

    附:GODEBUG=asyncpreemptoff=1可以禁用掉Go1.14的基于信号的抢占式调度而使用以前的基于 协作的抢占式调度以方便出现问题时对比两种调度。