Golang调度器

栏目: Go · 发布时间: 5年前

内容简介:本文尽量通俗易懂地讲Go调度器(scheduler)的相关知识,尤其是普通开发者能够关注和控制的部分。调度器本身十分复杂,所以下文难免有疏漏,发现后会尽量及时更新。参考链接:

本文尽量通俗易懂地讲 Go 调度器(scheduler)的相关知识,尤其是普通开发者能够关注和控制的部分。调度器本身十分复杂,所以下文难免有疏漏,发现后会尽量及时更新。

要点

  1. go程序的运行,以goroutine为单位,而goroutine实际运行在某个系统线程内。goroutine(可以非常多)和系统线程(相对比较少)并非一一对应。调度时,既有os调度线程,也有go调度器本身调度goroutine。简言之,go原生支持并发,go调度器负责将各个goroutine调度到不同的操作系统线程中取执行。
  2. 三个定义:
    • G: goroutine,就是平常提到的go中的协程
    • P: process,处理器,有的文章说代表上下文,也可以理解为附带有上下文信息的令牌
    • M: machine,线程,就是平常提到的操作系统中的线程
  3. Go早期是GM模型,后来因为性能问题转而使用GPM模型
  4. 执行机制:
    GOMAXPROCS
    

细节

  1. GM到GPM

    早期,GM模型有诸多问题,例如全局锁,M缓存内存占用浪费等,详见《 Scalable Go Scheduler Design 》。因此,大神操刀加了一层中间层(P),调度模型变成GPM,沿用至今(盗图一张):

    Golang调度器

    GPM调度模型

    通俗地讲,G要运行,需要绑定一个P(放在P的本地队列里),然后由与P绑定的操作系统线程M真正执行。
    G切换时,只是M从G1切到G2而已,都是在用户态进行着,非常轻量,不像操作系统切换M时比较重。
    P的本地队列中缺少G时,会从其他P的队列里“偷”一些或者从全局队列里取。
    借助于netpoller,发起网络调用时,G阻塞,M不阻塞,切换G即可。而发起文件IO等操作时,会执行(阻塞的)系统调用,(注:现在应该实现了部分poller for os package),此时M也会等待系统调用的返回。M和G一起,会解除与P的绑定。如果P的本地队列还有其他G,就会绑定另外一个空闲的M,如果没有,则新建一个M,然后继续执行可以执行的G。
  2. 调度器实现了抢占

    也就是说如果一个G执行太久,是会被切换出去的。

    这样可以确保整个程序看起来是“并发”执行的,而不是一个G可以执行时就是一直执行,其他G都饿死。

    但是 切换点需要是函数调用 。假设G中是不调函数的纯无限循环计算,还是无法被抢占。

  3. 什么时候G会被调度

  • 被sysmon设置为抢占
  • channel阻塞或网络IO
  • mutex等同步导致阻塞
  • 使用go关键字创建goroutine
  • GC过程中各种策略导致的调度
    runtime中,网络IO的实现采用了kqueue (MacOS), epoll (Linux)或iocp (Windows) 。
  1. 查看各种调度状态

    执行命令的时候,设置 GODEBUG 环境变量。例如: GODEBUG=schedtrace=1000 godoc -http=:6060

  2. P有local队列的好处

    其实好处有好几点。比较明显的是,GM模型里面,M切换G时,需要从全局队列里面取,需要加锁。GPM中,M绑定着P,M切换的G都在P的本地G队列中,不需要锁。

  3. P默认是机器逻辑核数

    因为超线程技术的存在,逻辑核数会与物理核数不同。下面的语句可以打印出逻辑核数,通过 GOMAXPROCS 设置时,可别弄错了

fmt.Println(runtime.NumCPU())
  1. M默认是10000

    M对应的是 sched.maxmcount ,默认10000。通过 SetMaxThreads 可修改,如果程序使用超过这个数,会自动crash!

// 改动时也会检查,并不能随意设置值
if in > 0x7fffffff { // MaxInt32
    sched.maxmcount = 0x7fffffff
} else {
    sched.maxmcount = int32(in)
}
  1. 相关代码片段(不详细研究的可以不用看了)

    参见下一篇吧,这篇已很长了。

参考链接:

  1. https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part2.html
  2. https://tonybai.com/2017/06/23/an-intro-about-goroutine-scheduler/

以上所述就是小编给大家介绍的《Golang调度器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mastering Regular Expressions, Second Edition

Mastering Regular Expressions, Second Edition

Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95

Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具