Go 读者提问:GPM 模型的 M 实际数量受什么影响?

大家好,我是煎鱼。

关于 Go 的 GMP 调度模型,我们之前写过一篇《Go 群友提问:Goroutine 数量控制在多少合适,会影响 GC 和调度?》进行深入讲解和分析。

当时有同学提出了如下问题:

4ed9d00b5f5116c5b6ef66258f3cb3a1.png

GPM 模型中,M 的实际数量,多或少受什么因素的限制呢?

作为一只鸽鱼,今天就给大家来讲讲,明确这一个小细节点。

回顾

之前有提到 Go 的调度模型离不开一个家庭里三个兄弟的互相协作,我们在此进行简单的回顾。

e34a8823705c7fd053caee063265bf82.png

这三位大哥分别是:G 弟、P 哥、M 爸,其分别承担如下作用:

  • G:Goroutine,实际上我们每次调用 go func 就是生成了一个 G。

  • P:Processor,处理器,一般 P 的数量就是处理器的核数,可以通过 GOMAXPROCS 进行修改。

  • M:Machine,系统线程。

三者的协作方式是:M: N 调度模型。M 必须与 P 进行绑定,然后不断地在 M 上循环寻找可运行的 G 来执行相应的任务。

前文已经把 G 和 P 的限制的因素说的很清楚了,如下图:

04af91af62a74e3995ddb0a282d8d3c8.png
来自《Go 群友提问:Goroutine 数量控制在多少合适,会影响 GC 和调度?》

下面会注重 M 的描述。

M 受影响因素

默认约束

M(Machine)是系统线程,在 Go 中默认的数量限制是 10000,如果超出则会报错:

GO: runtime: program exceeds 10000-thread limit

可以通过 debug.SetMaxThreads 的方法进行调整上限数量。

实际数量

那 M 的实际数量和什么有关系呢?本质上与 M 是否空闲和是否忙碌有关。

如果在调度时,发现没有足够的 M 来绑定 P,P 中又有需要就绪的任务,就会创建新的 M 来绑定。

如果有空闲的 M,自然也就不会创建全新的 M 了,会优先使用。

源代码

对应创建 M 的代码是 startm 函数。

源代码(src/runtime/proc.go)如下:

func startm(_p_ *p, spinning bool) {
 ...
 nmp := mget()
 if nmp == nil {
  id := mReserveID()
  unlock(&sched.lock)

  var fn func()
  if spinning {
   fn = mspinning
  }
  newm(fn, _p_, id)
  releasem(mp)
  return
 }
 ...
}

通过 mget 函数获取是否有空闲的 M,若无,则会调用 newm 函数创建一个新的 M 来应用,逻辑不会太复杂。

可能会有同学想问,那在什么场景下会涉及呢?理论上只要是 Go 调度器运行的过程中,发现满足条件都有可能会创建。

没必要太死记硬背,因为这个场景是会不断增加的,记住 GMP 模型的基本原则和三者的影响因素就可以了。

总结

这篇文章主要是针对前文的补充,增强了在 GMP 模型中 M 的实际数量的影响因素和源代码的逻辑处的介绍。

作为抛砖引玉,希望对大家在 Go 的调度模型上有一些帮助。

关注煎鱼,获取业内第一手消息和知识 👇

1b3481556e10dcf198a07f82ba1f6596.png

7eeaa3b3fe45c10f6cafe27ec4331d27.png

你好,我是煎鱼,出版过 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,和大家交流!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值