GMP模型

为什么G轻量
  • 1、内核线程初始栈空间2M,协程初始栈空间2KB,自动扩容
  • 2、内核需要频繁用户态内核态进行切换,切换成本较高
  • 3、当协程阻塞时,调度器可以挂起协程,运行其他协程,提高利用率
  • 4、线程间切换成本更高,协程间切换需要保存的运行现场更少
线程切换主要开销
  • 切换内核栈
  • 切换硬件上下文
  • 保存寄存器中的内容
  • cpu告诉缓存失效
为什么需要P
  1. 全局runq保存goroutine协程,造成对锁依赖严重,效率低
  2. M创建的G被放到其他M上运行,破坏了局部性原则,造成不必要的系统开销
  3. 每个M都需要分配内存,而真正执行中的M仅占1%
  4. 存在系统调用时,M会被阻塞,无法执行其他任务,造成系统资源浪费
  5. P能实现work stealing 机制和hand off
G的状态

1、Gidle 2、Grunnable 3、running 4、syscall 5、waiting 6、dead 7、copystack 8、preempted

GPM模型
  • goroutine来自协程的概念,让一组可复用的函数运行在一组线程之上,一个goroutine只占几KB,所以可以灵活调度,高并发
  • 如果只有G和M的话,M想要执行G都必须要访问全局G队列,并且M有多个,即多线程访问同一资源需要加锁进行保证互 斥/同步,所以全局G队列是有互斥锁进行保护的。 这就形成了激烈的锁竞争
  • 只后引进了P,如果线程想运行goroutine,必须先获取P,P中还包含了可运行的G队列

  • 全局队列(Global Queue):存放等待运行的G。

  • P的本地队列:同全局队列类似,存放的也是等待运行的G,存的数量有限,不超过256个。新建 G’时,G’优先加入到P的本地队列,如果队列满了,则会把本地队列中一半的G移动到全局队列。
  • P列表:所有的P都在程序启动时创建,并保存在数组中,最多有 GOMAXPROCS (可配置)个。
  • M:线程想运行任务就得获取P,从P的本地队列获取G,P队列为空时,M也会尝试从全局队列拿一 批G放到P的本地队列,或从其他P的本地队列偷一半放到自己P的本地队列。M运行G,G执行之 后,M会从P获取下一个G,不断重复下去。
  • Go语言调度器使用了一种策略:P 中每执行61次调度,就需要优先从全局队列中获取一个G到当前P中, 并执行下一个要执行的G
  • 没有足够的M来关联P并运行其中的可运行的G。比如所有的M此时都阻塞住了,而P中还 有很多就绪任务,就会去寻找空闲的M,而没有空闲的,就会去创建新的M。

  • hand off机制

  • Go语言的 hand off 机制 和 work steaing 机制一样,也是一种用于调度协程(Goroutines)的策略,有助于充分利用多核 CPU,提高并发性能,减少线程空转,从而使 Go 程序更高效地运行 核心思想是当线程 M 因为 G 进行的系统调用阻塞时,线程释放绑定的 P,把 P 转移给其他空闲的 M 执行
  • Go scheduler 可以说是 Go 运行时的一个最重要的 部分了。 Runtime 维护所有的 goroutine ,并通过 scheduler 来进行调度。
goroutine什么时候会被挂起
  • 发生阻塞,例如等待 I/O 操作的完成或者发送或接收通道上的数据时没有可用的对等方。
  • 发生调用 runtime.Gosched(),让出 CPU 给其他 goroutine 执行。
  • 发生同步操作,例如 sync.Mutex 或 sync.WaitGroup 的锁定和解锁操作。
  • 发生垃圾回收(GC)。
  • 发生错误,例如 panic 或者超时
在以下情形下,会切换正在执行的goroutine
  • 抢占式调度 sysmon 检测到协程运行过久(比如sleep,死循环) 切换到g0,进入调度循环
  • 主动调度 新起一个协程和协程执行完毕 触发调度循环 主动调用runtime.Gosched() 切换到g0,进入调度循环 垃圾回收之后 stw之后,会重新选择g开始执行
  • 被动调度 系统调用(比如文件IO)阻塞(同步) 阻塞G和M,P与M分离,将P交给其它M绑定,其它M执行P的剩余G 网络IO调用阻塞(异步) 阻塞G,G移动到NetPoller,M执行P的剩余G atomic/mutex/channel等阻塞(异步) 阻塞G,G移动到channel的等待队列中,M执行P的剩余G

资料:https://mp.weixin.qq.com/s/jIWe3nMP6yiuXeBQgmePDg

results matching ""

    No results matching ""