CFS 公平调度带宽控制 Throttle Model 演进历史
技术简介
CFS (Completely Fair Scheduler) 带宽控制是 Linux 内核 cgroup 的 cpu 子系统中的核心功能,允许对 task group 使用的 CPU 时间进行硬限制。当 task group 在给定周期内消耗的 CPU 时间超过其配置的 quota 时,该 group 中的任务将被 throttle(节流)——即暂时阻止其继续运行,直到下一个周期的配额刷新。
演进总览
CFS 带宽控制的 throttle model 经历了从 per-CFS_RQ 的全队列实体出队模型 到 per-task 的 task-based throttle 模型 的根本性架构变迁。该功能由 Paul Turner (Google) 于 2011 年在 Linux v3.2 中首次引入,历经十余年的演进,在 2025 年的 Linux v6.18 中完成了向 task-based throttle 的范式转换。
- 最初的 per-CFS_RQ 模型(v3.2):当 cfs_rq 被 throttle 时,整个队列的所有任务都被出队,等价于将该 CPU 上的整个 group "断电"。
- 中期演进(v3.2~v5.x):解决了一系列的正确性问题——PELT 统计处理、race condition、饥饿问题。
- Burst 支持(v5.14):引入 burstable CFS controller,允许 group 借用之前未用完的配额。
- Async Unthrottle(v6.3):使 unthrottle 能够通过 IPI(CSD)异步完成,避免在 period timer 中长时间持有 rq lock。
- Task-based Throttle 模型(v6.18):架构级变革——不再将整个 cfs_rq 从 rq 中移除,而是通过 task work 机制逐个将任务在返回用户态时 dequeue,大幅降低持有内核资源的阻塞延迟。
关键里程碑时间线
| 时间 | 内核版本 | 里程碑事件 | 贡献者 |
|---|---|---|---|
| 2011-07 | v3.2 | 初始实现:per-CFS_RQ throttle 模型 | Paul Turner |
| 2012-10 | v3.7 | 跨 throttle 周期的 runnable average 维护 | Paul Turner |
| 2013-10 | v3.12 | 修复 throttle 与 period timer 竞态 | Ben Segall |
| 2016-06 | v4.7 | 重写 throttle_count 同步机制 | Peter Zijlstra |
| 2018-10 | v4.19 | 修复 throttle_list 饥饿问题 | Phil Auld |
| 2020-01 | v5.5 | 阻止已 throttle group 无限运行 | Vincent Guittot |
| 2020-04 | v5.7 | 消除 throttle 与 distribution 间的竞态 | Paul Turner |
| 2021-06 | v5.14 | 引入 burstable CFS controller | Huaixin Chang |
| 2022-11 | v6.3 | Async unthrottle (CSD) | Josh Don |
| 2025-08 | v6.18 | 切换到 Task-based throttle 模型 | Valentin Schneider, Aaron Lu |
核心源代码文件
| 文件 | 说明 |
|---|---|
kernel/sched/fair.c | 全部 throttle/unthrottle、带宽分配、计时器逻辑 |
kernel/sched/sched.h | struct cfs_bandwidth, struct cfs_rq 中 throttle 相关字段 |
include/linux/sched.h | task_struct 中 throttle 相关字段(throttled, sched_throttle_work) |
kernel/sched/core.c | sched_task_is_throttled(), cgroup 接口 |
章节导航
- 第 1 章:起源与初始实现 —— per-CFS_RQ Throttle Model
- 第 2 章:初期演进 —— 在正确性与性能之间
- 第 3 章:Burst 支持与 Async Unthrottle
- 第 4 章:Task-based Throttle Model 转型
- 附录
统计数据速览
| 指标 | 数值 |
|---|---|
| 首次引入时间 | 2011-07, Linux v3.2 |
| 核心贡献者 | Paul Turner, Peter Zijlstra, Vincent Guittot, Ben Segall, Aaron Lu, Josh Don, Valentin Schneider 等 |
| 截至最新版的 throttle/bandwidth 相关 commit 数 | ~176 个 |
| 当前核心实现文件 | kernel/sched/fair.c |
| 代码覆盖(核心 throttle 路径) | ~500+ 行 |