本文地址:https://www.ebpf.top/post/bpf_sched_ext

1. 插拔调度器的萌芽【2004 年】

在 2004 年,Linux 社区的 Con Kolivas 提出了可插拔式调度器想法,旨在让内核中存在多个调度器,用户可在引导时选择。提交 patch 的工作原理是将大量代码拆分为 kernel/sched.c 公共部分和私有部分,同时在scheduler.c 文件中指向处理调度任务的函数的指针,这些函数被调用于各种进程事件( fork()exit() 等),以获取与调度相关的信息。实现新的调度程序只是编写相关函数的替换并整合即可。但该提交收到社区开发者 Ingo Molnar 的强烈反对,他认为内核有可插拔的调度器,调度域补丁永远不会出现,取而代之的是,将有一个单独的 NUMA 调度程序、一个 SMP 调度程序等。

Ingo Molnar 的观点很明确:大家都搞自己的小家庭,调度器这个大家庭就会没有人来组织和贡献代码,调度器将会以一个个特殊场景的调度器而存在。

关于这次讨论,我没有找到更多的细节资料,但是注定这是个失败的尝试。

2. Roman 首次尝试基于 BPF 调度器可编程能力【2021 年】

时间飞快,在 10 年后的 2014 年被称之为内核超能力的 BPF 技术合入到内核,并逐步在可观测、网络和安全等领域取得了令人瞩目的成就,BPF 也从内核中网络子模块中脱颖而出成为内核中的顶级的子模块。将 BPF 的可编程能力应用于调度器,实现其从配置化转向可编程化,成为了一个非常具有吸引力的方向。

2021 年 9 月份的 Facebook 的 Roman Gushchin 提交了一组 BPF 与调度器相关的 patch 提交 (由 6 个小的 patch 组成)。通过该补丁集,Roman Gushchin 希望能引发一场关于如何在调度器中使用 BPF 的对话,但是也有部分调度器专家也表达了顾虑,认为补丁提供的机制可能会导致大家针对各自的场景以特定方式的进行微优化,而对推动社区在调度器上进行更大力度的优化造成障碍(注:大家的担心和 2004 年的讨论的担心基本类似)。自然这是一个众口难调的话题,存在共性就会存在个性化,能够提供个性化定制的手段大多数场景下都会是一个不错的方案。

RomanGushchin

图 Roman Gushchin (来自与 GitHub)

初次看到 BPF 在调度器方面的提交,我还特意写了一篇文章当 BPF 邂逅 CPU 调度器来介绍相关内容。但 Roman 这次提交经过几轮讨论,并未在调度器社区没有引起太大的水花,同时我也注意到 2022 年 7 月份邮件列表讨论,Yafang Shao 也给出了一些建议,Roman 表示会在下个版本修复,但迟迟也未没有看到 patch 新版本发布。后续作者 Roman 在邮件回复中表示自己当前精力并不在这个方向,未来可能会持续。Roman 这次的努力,无论是从代码提交准备和版本提交乏力,都表明准备并不是非常充分,但是这次尝试的确打开了 BPF 和内核调度器的对话。但 Roman 已经成功撒播了种子,而种子也终将发芽。

3. Tejun Heo 接过大旗再战【2022 年】

[Tejun Heo]

图 Tejun Heo (2019)

2022 年 11 月,Tejun Heo(Meta) 接过大旗,与 David Vernet(Meta)、Josh Don(Google)Barret Rhoden(Google)往 Linux 社区一个由 30 个小 patch 组成的提交(61 files changed, 9672 insertions(+), 136 deletions(-) ),重启 BPF 进攻调度器的战役,将其称之为 sched_ext,核心思想为允许将调度策略实现为 BPF 程序,同时提交也提到该想法得到了部分 Google 公司内核活跃开发者的支持。

Tejun 在补丁提交中,关于引入 sched_ext 的价值给出了相当篇幅的说明,核心点包括:

  • 易于实验和探索:实现新调度策略的快速迭代。

    在这个章节 Tejun 花了大量文字针对必要性说明,我这里仅给出部分总结:

    • **调度器的复杂性:**CPU 架构变化、系统演进和用例变化,导致调度器复杂度急剧上升;

    • **实验的重要性:**AMD 和 Google 都进行了大量调度器相关的实验,华为也在进行类似调度器可编程的工作;

    • **CFS 调度器遇到的挑战:**扩展困难且耗时,门槛高见效慢,成为学术界助力调度器演进的障碍;

    • s**ched_ext 的优势和权衡:**sched_ext 通过提供一个可访问的调度实验框架来解决这些挑战。sched_ext 提供了便捷的回调和辅助函数简化常见操作,减少了复杂性。使用 BPF(Berkeley Packet Filter)确保了安全性,通过静态分析程序防止系统崩溃,允许安全实验和快速迭代。sched_ext 简化了调度实验,促进了机器学习的整合,在 Nginx 基准测试中实现了 15% 的吞吐量提升。

    同时 Tejun 也提到 sched_ext 提供的一个关键优势是 BPF 的使用。 BPF 通过在加载时静态分析程序来提供强大的安全保证,以确保它们不会损坏或崩溃系统。无论加载什么 BPF 调度程序,sched_ext 都能保证系统完整性,并提供安全禁用当前 BPF 调度程序并将任务迁移回可信调度程序的机制。

    长话短说就是,由于现代系统的日益复杂,调度中的探索至关重要。像 sched_ext 这样的工具显著降低了进入门槛,支持快速实验,可能会在调度器设计和性能方面带来变革性进步

  • **可定制:**构建特定于应用程序的调度程序,这些调度场景并不适用于通用调度程序的策略。

    sched_ext 通过提供灵活的调度策略,使用户能够实现应用程序特定的调度器。与改进 CFS 不同,定制调度器可以针对特定应用或硬件进行优化,同时也更好适应航空等特定行业调度场景。虽然 sched_ext 可能增加调度器实现的碎片化,但其提供的实验平台有助于提升整体性能和发展。

  • 快速调度程序部署:在生产环境中无中断地切换调度策略。

    内核版本升级通常缓慢,可能需要数月时间,尤其在修复错误时。Livepatch 适用范围有限,无法修补调度策略。sched_ext 可快速推广新调度策略,如解决 L1TF 漏洞的核心调度。虽然核心调度上游过程漫长,但 sched_ext 可快速部署应对。谷歌曾通过 sched affinity 缓解低优先级负载导致的性能问题,sched_ext 允许快速试验和部署新策略,直到上游解决方案出现。

不得不说 Tejun 总结能力的优秀,从多场景讲述了 sched_ext 的价值意义和达成路径。简单说就是:核心调度器复杂,已经难以适用现代硬件架构和特定场景,而且演进生效缓慢,也阻碍了学术界在调度器方面的研究,而 sched_ext 则可以解决上述问题。 sched_ext 通过其灵活性快速部署解决生产中的问题和赋予调度器学术领域新的活力。这一系列的陈述相信能够激发大家对 sched_ext 的兴趣和后续的支持。

4. Tejun 多次努力遭受调度器大佬明确拒绝【2023 年】

此后 Tejun 再接再励,分别于 1 月、4 月、7 月陆续提交了对应的 V2V3V4 版本

V4 版本的提交中, Tejun 总结到自从最初发布补丁集以来已半年有余,我们相信已经解决了前期反馈的问题,我们觉得 sched_ext 现在似乎已经足够成熟可以合入到主线中了,那么大家的意见呢?我准备好了,大家也都多多支持。

Barret Rhoden(Google)【提交作者之一】 首先回复表示了支持。同时 Barret 表示在谷歌仍在基于 ghost 进行调度器的实验和开发,这些后续都可移植到 sched_ext 上;Google 内部也开始进行 sched_ext 补丁测试,但是由于补丁依赖,还未启用,有进展会及时同步。

Linux 调度器维护者 Peter Zijlstra 也开始参与到整体讨论中。2023 年 7 月 21 号, Peter Zijlstra 明确表示了不会合入该提交(So, since you wanted it in writing, here goes: NAK)。并且 Peter Zijlstra 补充说,他认为合并代码没有任何价值,并退出了对话。 [Peter Zijlstra]

图 Peter Zijlstra 2009

I’m still hating the whole thing with a passion.

As can be seen from the wide-spread SCHED_DEBUG abuse; people are, in general, not interested in doing the right thing. They prod random numbers (as in really, some are just completely insane) until their workload improves and call it a day.

There is not a single doubt in my mind that if I were to merge this, there will be Enterprise software out there that will mandate its own BPF sched thing, or else it won’t work.

They will not care, they will not contribute, they might even pull a RedHat and only share the code to customers.

We all loose in that scenario. Not least me, because I get the additional maintenance burden.

I also don’t see upsides to merging this. You all can play with schedulers out-of-tree just fine and then submit what actually works.

So, since you wanted it in writing, here goes:

NAK

我依然非常讨厌整个事情。

从广泛滥用 SCHED_DEBUG 可以看出,人们通常不关心做正确的事情。他们会随意调整一些数字(有些真的完全是胡来的),直到他们的工作负载有所改善,然后就算完成了。

毫无疑问,如果我合并这个补丁,企业软件将会要求自己的 BPF 调度器,否则就无法工作。

他们不会在意,也不会贡献代码,甚至可能像 RedHat 那样只把代码分享给客户。

在这种情况下,我们所有人都会输。尤其是我,因为这会增加额外的维护负担。

我也看不到合并这个补丁的好处。你们完全可以在以 out-of-tree 的方式开发调度器,然后提交那些真正有效的东西。

所以,既然你们想要书面回复,那就这样吧:

NAK(不予接受)

自然,Tejun 不同意人们提出的许多担忧。他表示,有些调度问题无法通过调整当前调度器来解决,特别是在像 Meta 这样的 “超大规模” 环境中。他不认同 Peter 认为 sched_ext 会造成维护负担,Tejun 认为 BPF 在内核其他模块都工作的很好。Tejun 认为让用户能够做一些新的事情是有益的,即使某些人选择使用新功能不可避免地会出现 “愚蠢的情况”。总之,Tejun 认为,反对者关注的是 sched_ext 的潜在成本(在他看来,这种成本被夸大了),而没有考虑到它会带来的好处。他回复到:

在许多生产环境中,工作负载行为的某些方面很难全面理解。工作负载通常非常复杂,由许多人不断开发,并与外部实体动态交互。调度是人们在尝试优化系统性能时会关注的领域。大多数人对调度器代码库不够熟悉,无法进行修改。即使他们熟悉,在生产环境中设置基准测试并循环不同的内核也常常不容易。选择可调节的参数并不令人惊讶,因为这是唯一可用的选项,调整参数经常会带来一些收益。但 sched_ext 的广泛可用将允许更容易和更广泛的实验,帮助我们学到更多关于调度的知识。

Meta 和 Google 都致力于分享我们学到的东西,包括代码和经验。

随着时间的推移,Tejun 分别与 2023.8.3 和 8.10 分别发送 ping 邮件,期望更多人的讨论。

但来自 Suse 实验室的 Mel Gorman 也表示支持 Peter Zijlstra 的观点,针对 Mel Gorman 的观点,Tejun 则进行了针对性的回复。

最后,Josh Don(Google)【提交作者之一】 回复表示支持 sched_ext,并且表示 Google 和 Meata 一起联合推进这项事情

我想重申谷歌对这个提案的支持(这是我们 Google 的支持态度),并表示插拔式调度器已经在 ghost 框架进行了一系列实验,有非常明显的效果,展望未来,我们计划重新设计 ghost 用户空间基础设施,以在 sched_ext 内核基础设施之上工作。我们认为 sched_ext 设计有很多好处,特别是非常紧密的 BPF 集成。我们致力于可插拔调度的理念,并与 Meta 密切合作推进这项工作,同时在内部部署。

2023 年 10 月这次对话结束后, sched_ext 合入的事情陷入了停滞状态。

5. Tejun Heo 完善版本并重启推动,曙光出现【2024 年】

2023 年 11 月和 2024 年 5 月,Tejun Heo 持续优化代码,分别提交了 V5V6 版本,大有不达目的不罢休的势头(毕竟背靠 Meta 和 Google 的支持,底气自然还是有的)。V5 版本代码提交更是涉及到了 74 个文件,17207 行代码新增和 105 行代码删除, V6 版本涉及 96 个文件修改,15056 行代码新增和 139 行代码删除。

2024 年 5 月初,Tejun Heo 基于 V6 版本重启了新一轮的 sched_ext 讨论,Tejun Heo 表示: Valve 计划使用 sched_ext 在 Steam Deck 上更好地调度游戏。 **Ubuntu 正在考虑在 24.10 版本中发布使用。 Meta 和 Google 正逐步在生产中的使用。**同时,人们也有兴趣 ChromeOS 中使用,Occulus 也在考虑采用。Tejun Heo 总结说:

Given that there already is substantial adoption which continues to grow and sched_ext doesn’t affect the built-in schedulers or the rest of kernel in an invasive manner, I believe it’s reasonable to consider sched_ext for inclusion.

鉴于已经有大量采用并持续增长,并且 sched_ext 不会以侵入方式影响内置调度程序或内核的其余部分,我认为考虑合入 sched_ext 是合理的。

同时 Tejun Heo 合作者之一的 David Vernet (Meta)也在 2024 年 5 月初的 LSFMM + BPF 大会上进行了 sched_ext 工作总结和最新进展。

V6 版本提交中,调度器维护者大佬 Peter Zijlstra 的态度尽管仍然持反对意见,但是明显有所松动,表示在 cgroup 问题未解决之前不会考虑这个补丁,同时也抱怨到既然你们 Meta 和 Google 愿意联合推出 sched_ext ,那么先把你们就应该合理解决你们留下的烂尾项目 cgroup 的问题再谈。

I fundamentally believe the approach to be detrimental to the scheduler eco-system. Witness the metric ton of toy schedulers written for it, that’s all effort not put into improving the existing code.

我从根本上认为这种方法对调度程序生态系统有害。见证为此编写的大量玩具调度程序,这些努力都没有投入到改进现有代码中。

尽管,Tejun 表示愿意(尽管不情愿)解决 cgroup 问题(但也明确表明立场 cgroup 问题和 sched_ext 提交无关,我愿意提供协助催促是看着解决这个问题能为 sched_ext 扫清合入的道路。

不过,Tejun 强烈不同意 Peter 将 sched_ext 调度程序描述为 “玩具调度程序“ 和使用 sched_ext 会占用主线调度程序的精力的说法。Tejun 表示不存在完美的 CPU 调度程序,因此主线调度程序必须满足所有用户的需求。这使得尝试 “激进的想法” 几乎是不可能的,并且严重限制了可以从事调度程序工作的人员数量。

尽管仍然存在分歧,但是随着 sched_ext 的影响力和 Tejun (Google + Meta)持续施压,调度器大佬 Peter 也不得不有所妥协,毕竟开源社区技术圈的问题也不全是技术的问题。sched_ext 的合入看到了一丝曙光。

6. 峰回路转,终极决策者 Linus 拍板 6.11 版本合入【2024.6.11】

sched_ext 首次提交,Linus 就有参与部分技术讨论。看着手下的小弟们在邮件组里你来我往,大 Boss Linus 也坐不住了。

2024 年 6 月 11 号,Linus 终于发话了,决定将 sched_ext 合入到 6.11 版本中。Linus Torvalds 是在不少内核开发者反对的情况下决定强制将该功能合入的,他在回复中提到:

linus-trovalds

I honestly see no reason to delay this any more. This whole patchset was the major (private) discussion at last year’s kernel maintainer summit, and I don’t find any value in having the same discussion (whether off-list or as an actual event) at the upcoming maintainer summit one year later, so to make any kind of sane progress, my current plan is to merge this for 6.11.

老实说,我认为没有理由再拖延了。这整个补丁集是去年内核维护者峰会上的主要(私人)讨论,我认为在一年后即将到来的维护者峰会上进行相同的讨论(无论是列表外还是实际活动)没有任何价值,所以为了取得任何理智的进展,我目前的计划是将其合并到 6.11 中。

至此,BPF 实现调度可编程化的 sched_ext 总算得到了解决,后续我们也将持续关注 sched_ext 在 6.11 内核版本合入的情况。在下篇文章我们将展开介绍一下 sched_ext 的机制及实现案例,敬请期待,作者水平有限,欢迎批评指正。