知识卡片

窃取平衡负载

结构图卡 · 1481.a.1

内容

当本地、全局和网络队列都找不到任务时,P 会从其他 P 的本地队列偷取一半任务。工作窃取让负载自动扩散,减少中心化调度锁竞争。

结构图

flowchart LR
    A[空闲 P] --> B{本地队列为空}
    B -->|是| C[查看全局队列]
    C --> D{仍无任务}
    D -->|是| E[从其他 P 窃取一半 G]
    E --> F[恢复执行负载]

参考来源

- 位置:《Go语言底层原理剖析》第15章《深入协程设计与调度原理》15.5.4节《协程窃取》 - 结论依据:原文说明"当局部运行队列、全局运行队列以及准备就绪的网络列表中都找不到可用协程时,需要从其他P的本地队列中窃取可用的协程执行",并用 findrunnable 函数中"随机遍历allp数组,找到可用的P就立即窃取"及 runqgrab 函数"将要窃取的P本地运行队列中Goroutine个数的一半放入自己的运行队列中",因此可以推出"空闲 P 会从其他 P 随机窃取一半任务来平衡负载"的结论。 - 原始内容:当局部运行队列、全局运行队列以及准备就绪的网络列表中都找不到可用协程时,需要从其他P的本地队列中窃取可用的协程执行……第2层for循环表示随机遍历allp数组,找到可窃取的P就立即窃取并返回……找到要窃取的P之后就正式开始窃取了,其核心代码位于runqgrab函数。窃取的核心逻辑比较简单……将要窃取的P本地运行队列中Goroutine个数的一半放入自己的运行队列中。