【译】GO的工作窃取调度程序

[toc]

前言

原文:Go's work-stealing scheduler

Go scheduler的工作是向运行在一个或多个处理器上的OS线程上分发可运行的goroutines。在多线程计算中,调度会出现两种形式:工作分享和工作窃取。

  • 工作分享:当处理器生成新线程时,它会尝试将其中一些线程迁移到其他处理器,并希望它们被闲置或未充分利用的处理器处理。
  • 工作窃取:未充分利用的处理器主动寻找其他处理器的线程并“窃取”一些。

与工作共享相比,工作窃取的线程迁移发生频率较低。当所有处理器都有工作要运行时,不会迁移任何线程。只要有空闲处理器,就会考虑迁移。

Go从1.1版本开始加入工作窃取调度,由Dmitry Vyukov提供。本文件将深入解释什么是“work-stealing” 以及go是如何实现的

调度基础知识

Go有一个M:N调度程序,可以使用多个处理器。在任何时候,M goroutines需要在N OS线程上进行调度,这些线程最多可运行处理器的GOMAXPROCS个。Go scheduler对goroutines,线程和处理器使用以下术语:

  • G: goroutine
  • M: OS thread (machine)
  • P: processor

这里有一个特定的本地P和一个全局goroutine队列。每个M需要分配给P。这些P如果被阻塞或正在执行系统调用则可能没有M,在任何时候最多存在GOMAXPROCS个P。在任何时候每个P上只能有一个M,如果需要,调度程序可以创建更多的M。

image

每轮调度只是简单的找到一个可运行的goroutine并执行它。在每轮调度中,搜索按以下顺序进行:

runtime.schedule() {
    // only 1/61 of the time, check the global runnable queue for a G.
    // if not found, check the local queue.
    // if not found,
    //     try to steal from other Ps.
    //     if not, check the global runnable queue.
    //     if not found, poll network.
}

一旦找到可运行的G,就会执行它直到它被阻止。

注意:看起来全局队列比本地队列有优势,但是为了避免M只在本地队列,直到没有本地队列goroutine剩余,检查一遍全局队列也是至关重要的。

窃取

当创建一个新的G或现有G变为可运行时,它被推送到当前P的可运行goroutine列表。当P完成执行G时,它尝试从自己的可运行goroutine列表中弹出G. 如果列表现在为空,则P选择随机的其他处理器(P)并尝试从其队列中窃取一半可运行的goroutine。

image

在上面的例子中,P2找不到任何可运行的goroutines。因此,它随机选择另一个处理器(P1)并窃取三个goroutine到它自己的本地队列。P2将能够运行这些goroutine,并且调度程序工作将在多个处理器之间更公平地分布。

旋转线程(spinning threads)

调度程序总是希望向M分配尽可能多的可运行的goroutine以利用处理器,但同时我们需要停止过多的工作来节省CPU和电源。与此相反,调度程序还需要能够处理高吞吐量和CPU密集型程序。

如果性能至关重要,则常量抢占是昂贵的且对于高吞吐量程序也是一个问题。操作系统线程不应经常在彼此之间切换可运行的goroutine,因为它会导致延迟增加。除了存在系统调用之外,OS线程需要不断被阻塞和解除阻塞。这是代价高昂的并且增加了很多开销。

为了最大限度地减少切换,Go调度程序实现了“旋转线程”。旋转线程消耗一些额外的CPU功率,但它们最小化了OS线程的抢占。在以下情况下线程正在旋转

  • 被分配了P的M,正在寻找可运行的goroutine。
  • 没有P分配的M正在寻找可用的P。
  • 如果有空闲的P并且没有其他旋转线程,调度程序也会取消停放一个额外的线程并在准备goroutine时旋转它。

在任何时刻最多有GOMAXPROCS个旋转M。当旋转线程找到工作时,它会使自己脱离旋转状态。

如果存在P赋值的空闲M,则具有P赋值的空闲线程不会阻塞。当创建新的goroutine或M阻塞时,调度程序确保至少有一个旋转M.这确保没有可运行的可运行的goroutine;并避免过多的M阻塞/解除阻塞。

结论
Go调度程序做了很多工作,以避免过多抢占操作系统线程,方法是通过窃取将它们安排到正确和未充分利用的处理器,以及实现“旋转”线程以避免阻塞/解除阻塞过渡的高频发生。

execution tracer可以跟踪调度事件。如果您碰巧认为处理器利用率较低,您可以调查发生了什么。

参考:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容