Linux 调度器性能优化分析报告

1. 概述

本报告详细分析了 Linux 调度器从 5.10 到最新版本(7.0-rc2)的性能优化特性,涵盖了调度策略、拓扑感知、缓存局部性、内存管理等多个方面的改进。通过这些优化,Linux 调度器在性能、可靠性和灵活性方面都得到了显著提升,能够更好地适应现代硬件和工作负载。

2. 各版本优化特性分析

2.1 5.10 到 5.15 版本

AMD CPPC 最大性能值修复

原理:修正了某些 AMD Ryzen 世代处理器的 CPPC(Collaborative Power and Performance Control)最大性能值计算,确保调度器能够正确识别和使用处理器的最大性能能力。

场景:适用于搭载 AMD Ryzen 处理器的系统,特别是那些在调度器中未能正确识别处理器性能上限的系统。

效果:提高了 AMD Ryzen 系统的性能和能效,使调度器能够更准确地根据工作负载调整处理器性能,避免了性能被人为限制的问题。

补丁:3743d55b289c x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations

新空闲平衡优化

原理:优化了空闲平衡算法,当检测到有任务唤醒待处理时,跳过 newidle_balance 操作,避免在任务即将被唤醒时进行不必要的负载平衡。

场景:适用于多处理器系统,特别是在任务频繁唤醒的场景下,如交互式应用、多线程服务器等。

效果:减少了不必要的调度开销,提高了系统响应速度,特别是在任务唤醒密集的场景下,能够更快地将唤醒的任务分配到合适的 CPU 上。

补丁:e5e678e4fea2 sched,fair: Skip newidle_balance if a wakeup is pending

ARM64 调度域重建

原理:当 ARM64 系统的 CPU 不变性状态发生变化时,重新构建调度域以适应新的硬件特性,确保调度器能够正确感知系统的拓扑结构。

场景:适用于 ARM64 系统,特别是那些 CPU 特性可能动态变化的系统,如某些节能模式下的处理器。

效果:提高了 ARM64 系统的调度效率和性能,确保调度器能够根据最新的硬件状态做出最优的调度决策。

补丁:ecec9e86d1a3 arm64: Rebuild sched domains on invariance status changes

2.2 5.15 到 5.19 版本

每 CPU 内核线程唤醒检测修复

原理:改进了调度器对每 CPU 内核线程唤醒任务的检测逻辑,确保正确识别由内核线程唤醒的任务,避免调度决策错误。

场景:适用于有大量内核线程活动的系统,如 I/O 密集型应用、网络服务器等。

效果:提高了内核线程唤醒的准确性和性能,确保被内核线程唤醒的任务能够得到及时的调度处理,减少了调度延迟。

补丁:8b4e74ccb582 sched/fair: Fix detection of per-CPU kthreads waking a task

schedstats 辅助函数独立化

原理:重构了 schedstats 相关代码,使其不再依赖于公平调度类,为其他调度类使用 schedstats 提供了便利。

场景:适用于需要在不同调度类中使用统计功能的场景,特别是在开发新调度类或扩展现有调度类时。

效果:提高了代码的可维护性和扩展性,为调度器的进一步发展奠定了基础,同时也使得不同调度类能够更方便地利用统计功能进行性能分析。

补丁:60f2415e19d3 sched: Make schedstats helpers independent of fair sched class

sched_statistics 结构独立化

原理:将 sched_statistics 结构从公平调度类中分离出来,使其可以被其他调度类使用,提高了代码的模块化程度。

场景:适用于多调度类共存的系统,特别是在需要统一统计接口的场景下。

效果:提高了代码的模块化程度,为调度器的扩展提供了更大的灵活性,使得不同调度类能够共享统计基础设施。

补丁:ceeadb83aea2 sched: Make struct sched_statistics independent of fair sched class

2.3 6.0 到 6.5 版本

mm_cid 性能回归修复

原理:解决了内存上下文 ID(mm_cid)管理中导致的性能问题,修复了由 mm_cid 引入的性能回归。

场景:适用于内存密集型工作负载,特别是在多进程、多线程环境下的内存操作。

效果:恢复了系统性能,特别是在内存密集型工作负载下,减少了内存上下文切换的开销,提高了系统的整体吞吐量。

补丁:223baf9d17f2 sched: Fix performance regression introduced by mm_cid

CFS 带宽定时器交错

原理:交错 CFS(完全公平调度器)带宽定时器的执行,减少定时器开销,提高低系统负载下单线程应用的性能。

场景:适用于低系统负载下运行单线程应用的场景,如桌面环境、轻量级服务器等。

效果:提高了低系统负载下单线程应用的性能,减少了定时器对应用执行的干扰,使得单线程应用能够获得更连贯的 CPU 时间片。

补丁:41abdba93747 sched: Interleave cfs bandwidth timers for improved single thread performance at low utilization

DRM 调度器优化

原理:移除了 drm_sched_dependency_optimized,简化了 DRM(直接渲染管理器)调度器的依赖管理,提高了调度器的效率。

场景:适用于图形处理、视频渲染等需要 DRM 调度器的场景,特别是在高帧率、高分辨率的图形应用中。

效果:提高了 DRM 调度器的效率和可维护性,减少了调度开销,使得图形处理能够更流畅地进行。

补丁:2cf9886e2816 drm/scheduler: remove drm_sched_dependency_optimized

2.4 6.5 到 6.10 版本

schedutil governor 性能估计改进

原理:重新设计了 schedutil CPU 频率调节器的性能估计算法,提高了 CPU 频率调节的准确性和效率。

场景:适用于所有使用 schedutil 调节器的系统,特别是在工作负载变化频繁的场景下。

效果:提高了 CPU 频率调节的准确性和效率,优化了能耗和性能之间的平衡,使得系统能够更快速地响应工作负载的变化。

补丁:9c0b4bb7f630 sched/cpufreq: Rework schedutil governor performance estimation

频率选择修复

原理:修复了非不变性情况下的频率选择逻辑,确保调度器能够为不同类型的 CPU 选择合适的频率。

场景:适用于具有不同性能特性的 CPU 系统,特别是在异构 CPU 架构中。

效果:提高了非不变性情况下的频率选择准确性,确保系统能够根据实际工作负载和 CPU 特性选择最优的运行频率。

补丁:e37617c8e53a sched/fair: Fix frequency selection for non-invariant case

mm_cid 内存屏障修复

原理:在 switch_mm_cid() 中添加了缺失的内存屏障,确保内存上下文 ID 的更新能够被正确地同步到所有 CPU。

场景:适用于多处理器系统,特别是在频繁切换内存上下文的场景下。

效果:提高了 mm_cid 操作的可靠性,避免了因内存屏障缺失导致的潜在一致性问题,确保了系统的稳定性。

补丁:fe90f3967bdb sched: Add missing memory barrier in switch_mm_cid

2.5 6.10 到 6.15 版本

sched_ext:BPF 可扩展调度器框架

原理:引入了全新的可扩展调度器框架,允许使用 BPF 程序定义自定义调度策略,无需修改内核即可实现调度器创新。

场景:适用于需要定制调度策略的场景,如特定工作负载优化、实时应用、高性能计算等。

效果:允许针对特定工作负载定制调度策略,提高性能;减少了内核修改的需要,通过 BPF 程序即可实现调度器创新;为调度器的发展提供了更大的灵活性。

补丁:f0e1a0643a59 sched_ext: Implement BPF extensible scheduler class

RSEQ 并发 ID 缓存局部性优化

原理:优化了 RSEQ(Restartable Sequences)并发 ID 的分配和管理,提高了缓存局部性,减少了缓存 misses。

场景:适用于使用 RSEQ 的应用程序,特别是在间歇性工作负载下,如 web 服务器、数据库等。

效果:提高了使用 RSEQ 的应用程序性能,减少了缓存开销,使得并发操作能够更高效地执行。

补丁:7e019dcc470f sched: Improve cache locality of RSEQ concurrency IDs for intermittent workloads

内存分配优化

原理:在 task_tick_mm_cid() 中禁用页面分配,避免了在调度器 tick 中进行可能导致阻塞的内存分配操作。

场景:适用于实时应用、低延迟场景,特别是对调度延迟敏感的应用。

效果:减少了调度延迟,提高了系统的响应速度,确保了调度器 tick 能够在有限的时间内完成,避免了因内存分配导致的调度延迟。

补丁:73ab05aa46b0 sched/core: Disable page allocation in task_tick_mm_cid()

sched_ext WAKE_SYNC 行为优化

原理:改进了 sched_ext 中默认空闲 CPU 选择的 WAKE_SYNC 行为,优化了唤醒同步时的 CPU 选择策略。

场景:适用于多线程应用,特别是在需要同步唤醒多个线程的场景下。

效果:减少了唤醒延迟,提高了多线程应用的性能,确保了唤醒的任务能够被分配到最合适的 CPU 上。

补丁:21b8964826c4 sched_ext: improve WAKE_SYNC behavior for default idle CPU selection

迁移局部性判断优化

原理:清理和重构了 migrate_degrades_locality() 函数,简化了迁移局部性判断逻辑,提高了代码的可读性和可维护性。

场景:适用于需要频繁进行任务迁移的系统,特别是在 NUMA 架构中。

效果:间接提高了调度器的性能和可靠性,便于后续的性能优化,确保了任务迁移决策的准确性。

补丁:c3856c9ce6b8 sched/fair: Cleanup in migrate_degrades_locality() to improve readability

2.6 6.15 到 6.19 版本

拓扑扫描性能优化

原理:优化了 topology_span_sane 函数的实现,减少了不必要的计算,提高了拓扑扫描的速度。

场景:适用于大型 NUMA 系统,特别是在需要频繁进行拓扑扫描的场景下。

效果:加快了调度器的拓扑感知速度,减少了调度决策的延迟,使得调度器能够更快速地适应系统拓扑结构的变化。

补丁:f55dac1dafb3 sched/topology: improve topology_span_sane speed

mm_cid 代码清理

原理:移除了 mm_cid_get() 中未使用的代码,简化了代码结构,提高了可维护性。

场景:适用于所有使用 mm_cid 的系统,特别是在代码维护和审计时。

效果:提高了代码的可维护性,减少了代码复杂度,便于后续的性能优化和 bug 修复。

补丁:53abe3e1c154 sched: Remove never used code in mm_cid_get()

2.7 6.19 到 7.0-rc2 版本

抢占模式进一步限制

原理:进一步限制了调度器的抢占模式,确保抢占操作能够更加安全和可预测。

场景:适用于实时应用、低延迟场景,特别是对抢占行为敏感的应用。

效果:提高了系统的稳定性和可预测性,减少了因抢占导致的潜在问题,确保了关键任务的执行时间。

补丁:7dadeaa6e851 sched: Further restrict the preemption modes

sched_ext 错误日志优化

原理:为 sched_ext 中的 dsq(dispatch queue)创建失败添加了错误日志,提高了调试能力。

场景:适用于使用 sched_ext 的系统,特别是在调试和故障排查时。

效果:提高了系统的可调试性,使得 sched_ext 的问题能够被更快速地识别和解决。

补丁:2f8d489897ae sched_ext: Add error logging for dsq creation failures

工具 sched_ext 错误日志优化

原理:为剩余调度器中的 dsq 创建失败添加了错误日志,提高了工具的调试能力。

场景:适用于使用 sched_ext 工具的系统,特别是在开发和测试新调度策略时。

效果:提高了工具的可调试性,使得 sched_ext 工具的问题能够被更快速地识别和解决。

补丁:bd4f0822f4ec tools/sched_ext: Add error logging for dsq creation failures in remaining schedulers

3. 技术深度分析

3.1 sched_ext 架构设计

sched_ext 是一个革命性的调度器框架,它通过以下方式实现了高度可扩展性:

3.2 调度器性能优化的关键技术

  1. 缓存局部性优化
    • 改进了 RSEQ 并发 ID 的缓存局部性,减少了缓存 misses
    • 优化了数据结构的访问模式,提高了 CPU 缓存的利用率
  2. 算法优化
    • 改进了拓扑扫描算法,减少了不必要的计算
    • 优化了唤醒同步行为,提高了多线程应用的性能
    • 简化了迁移局部性判断逻辑,提高了代码的可读性和效率
  3. 内存管理优化
    • 避免了调度器 tick 中的页面分配,提高了调度器的实时性
    • 修复了 mm_cid 相关的内存屏障问题,确保了内存操作的一致性
  4. 硬件感知优化
    • 修复了 AMD CPPC 最大性能值,确保调度器能够正确识别处理器性能
    • 在不变性状态变化时重建调度域,适应硬件特性的变化
    • 改进了 schedutil governor 性能估计,优化了 CPU 频率调节
  5. 代码重构与简化
    • 使 schedstats 辅助函数独立于公平调度类,提高了代码的模块化程度
    • 使 struct sched_statistics 独立于公平调度类,为调度器的扩展提供了更大的灵活性
    • 清理了未使用的代码,提高了代码的可维护性

4. 性能影响评估

优化特性 性能提升 适用场景 技术收益
sched_ext 框架 特定工作负载、定制化调度需求 灵活的调度策略定制,针对特定工作负载的性能优化
拓扑扫描优化 大型 NUMA 系统 加快拓扑感知速度,减少调度延迟
RSEQ 缓存局部性优化 间歇性工作负载、使用 RSEQ 的应用 减少缓存开销,提高应用性能
唤醒同步行为优化 多线程应用 减少唤醒延迟,提高线程协作性能
内存分配优化 低到中 实时应用、低延迟场景 提高调度器实时性,减少延迟
CFS 带宽定时器交错 低到中 低系统负载下的单线程应用 提高低负载下单线程性能
schedutil 性能估计改进 所有场景 优化 CPU 频率调节,提高能耗效率
AMD CPPC 修复 AMD Ryzen 系统 提高处理器性能利用率

5. 相关补丁集

5.1 5.10 到 5.15 版本

3743d55b289c x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations e5e678e4fea2 sched,fair: Skip newidle_balance if a wakeup is pending ecec9e86d1a3 arm64: Rebuild sched domains on invariance status changes

5.2 5.15 到 5.19 版本

8b4e74ccb582 sched/fair: Fix detection of per-CPU kthreads waking a task 60f2415e19d3 sched: Make schedstats helpers independent of fair sched class ceeadb83aea2 sched: Make struct sched_statistics independent of fair sched class

5.3 6.0 到 6.5 版本

223baf9d17f2 sched: Fix performance regression introduced by mm_cid 41abdba93747 sched: Interleave cfs bandwidth timers for improved single thread performance at low utilization 2cf9886e2816 drm/scheduler: remove drm_sched_dependency_optimized

5.4 6.5 到 6.10 版本

9c0b4bb7f630 sched/cpufreq: Rework schedutil governor performance estimation e37617c8e53a sched/fair: Fix frequency selection for non-invariant case fe90f3967bdb sched: Add missing memory barrier in switch_mm_cid

5.5 6.10 到 6.15 版本

f0e1a0643a59 sched_ext: Implement BPF extensible scheduler class 7e019dcc470f sched: Improve cache locality of RSEQ concurrency IDs for intermittent workloads 73ab05aa46b0 sched/core: Disable page allocation in task_tick_mm_cid() 21b8964826c4 sched_ext: improve WAKE_SYNC behavior for default idle CPU selection c3856c9ce6b8 sched/fair: Cleanup in migrate_degrades_locality() to improve readability

5.6 6.15 到 6.19 版本

f55dac1dafb3 sched/topology: improve topology_span_sane speed 53abe3e1c154 sched: Remove never used code in mm_cid_get()

5.7 6.19 到 7.0-rc2 版本

7dadeaa6e851 sched: Further restrict the preemption modes 2f8d489897ae sched_ext: Add error logging for dsq creation failures bd4f0822f4ec tools/sched_ext: Add error logging for dsq creation failures in remaining schedulers

6. 结论

从 Linux 5.10 到最新版本(7.0-rc2),调度器领域经历了重大创新和改进,特别是 sched_ext 框架的引入,为 Linux 调度器带来了前所未有的灵活性和可扩展性。这些优化不仅提高了调度器的性能,还为特定工作负载的定制化调度策略提供了可能。

主要的性能提升来自于:

这些优化使得 Linux 调度器能够更好地适应现代硬件和工作负载,为各种应用场景提供了更好的性能和可靠性。未来,随着 sched_ext 生态的发展,我们可以期待看到更多针对特定工作负载的优化调度策略,进一步提升 Linux 系统的性能和可靠性。