shitaibin.github.io
shitaibin.github.io copied to clipboard
Go调度器系列(3)图解调度原理 | 大彬 LIB
http://lessisbetter.site/2019/04/04/golang-scheduler-3-principle-with-graph/
如果你已经阅读了前2篇文章:《调度起源》和《宏观看调度器》,你对G、P、M肯定已经不再陌生,我们这篇文章就介绍Go调度器的基本原理,本文总结了12个主要的场景,覆盖了以下内容: G的创建和分配。 P的本地队列和全局队列的负载均衡。 M如何寻找G。 M如何从G1切换到G2。 work stealing,M如何去偷G。 为何需要自旋线程。 G进行系统调用,如何保证P的其他G’可以被执行,而不是饿死。
您好, 场景4:g2在创建g7的时候,发现p1的本地队列已满,需要执行负载均衡,把p1中本地队列中前一半的g,还有新创建的g转移到全局队列。 这一点不是太明白,为什么要把本地队列中的前一半g转到全局队列,而不是后一半g
@n0trace 您好, 场景4:g2在创建g7的时候,发现p1的本地队列已满,需要执行负载均衡,把p1中本地队列中前一半的g,还有新创建的g转移到全局队列。 这一点不是太明白,为什么要把本地队列中的前一半g转到全局队列,而不是后一半g
好问题。代码没有相关的解释,这是我的理解: P保存的G是一个FIFO队列,把前面的一半放到全局队列,全局队列的G可能被其他P偷走去执行,可能会被多个P偷走,这样可以尽量让前面的一半会比后面的一半先执行。
go调度解释到这么详细,赞!尤其是结合图示讲解,酣畅淋漓
作者,场景8是不是画错了,我看你各个平台都不回复的,自己的博客应该回复的吧?
场景10:假定当前除了m3和m4为自旋线程,还有m5和m6为自旋线程,g8创建了g9,g8进行了阻塞的系统调用,m2和p2立即解绑,p2会执行以下判断:如果p2本地队列有g、全局队列有g或有空闲的m,p2都会立马唤醒1个m和它绑定,否则p2则会加入到空闲P列表,等待m来获取可用的p。本场景中,p2本地队列有g,可以和其他自旋线程m5绑定。
您好, 请问在解绑后,如果p2本地队列有g、全局队列有g,但是没有空闲的m,此时p2是怎么唤醒一个m和它绑定的?
@KylinGu
场景10:假定当前除了m3和m4为自旋线程,还有m5和m6为自旋线程,g8创建了g9,g8进行了阻塞的系统调用,m2和p2立即解绑,p2会执行以下判断:如果p2本地队列有g、全局队列有g或有空闲的m,p2都会立马唤醒1个m和它绑定,否则p2则会加入到空闲P列表,等待m来获取可用的p。本场景中,p2本地队列有g,可以和其他自旋线程m5绑定。
您好, 请问在解绑后,如果p2本地队列有g、全局队列有g,但是没有空闲的m,此时p2是怎么唤醒一个m和它绑定的?
调用handoff函数可以转移p,具体看这个调用链:entersyscallblock -> entersyscallblock_handoff -> handoffp
@KylinGu 作者,场景8是不是画错了,我看你各个平台都不回复的,自己的博客应该回复的吧?
抱歉,其他平台现在很少登录了。
场景8的图左边少了g8,已更新新图。
场景7,本地队列没有g时,是优先从其他P的本地队列窃取还是从全局队列窃取?这里Scheduling In Go : Part II - Go Scheduler图10~图13我看说的是优先从其它P的本地队列窃取,当其它P也没有g时,才从全局队列窃取。但是有1/61的概率是优先从全局队列获取stealing work,此时需要加锁。这里没有看太明白,不清楚楼主是否清楚这个是出于什么考虑?