go

Go GPM

Posted by keming on August 29, 2021

GPM的几个关键点

  • 文章参考:https://www.jianshu.com/p/fa696563c38a

  • 刘丹冰大佬的github总结:https://github.com/aceld/golang

理解

  • 名称
    • G:go routine 协程
      • 有些地方说跟协程还不完全一样,但大概可以这么理解。
    • P:Processor 调度器
    • M:内核线程
  • 绑定关系
    • P和M在同一时刻一一对应,如果发生解绑,P会再对应一个别的M。
    • G总是要放在一个M上才能运行,实际上是多个G在不同时刻复用M。
  • M怎么取到G
    • 首先,从对应P的本地G队列拿(为了局部性)
    • 拿不到就从全局G队列获取到本地G队列,不会拿很多,防止别的P/M拿不到
    • 全局也没有的话就从别的正常P/M本地G队列里面偷一点
    • 实在没有就只能自旋了,有一个空闲P队列维护了空闲的P/M组合
      • 因为自旋费CPU,所以P有上限,由GOMAXPROCS控制,一般我觉得搞成线程数合适
  • G产生的G放哪里
    • 首先尝试放本地G队列(局部性)
    • 要是本地满了,就把本地G队列的一半G挪到全局G队列(负载均衡)
    • 继续放,就能放在本地G队列
  • G运行的时候阻塞怎么办
    • 直接把G/M组合和P解绑
    • P获取新的M(从休眠M队列里面拿,或者重新创建),跑新的G
    • 阻塞的G等到它阻塞结束,自己去找一个P(原先的P或者空闲P队列
      • 找不到P就只能解散了,M自己去休眠,G放到全局等分配