本报告详细分析了 Linux 调度器从 5.10 到最新版本(7.0-rc2)的性能优化特性,涵盖了调度策略、拓扑感知、缓存局部性、内存管理等多个方面的改进。通过这些优化,Linux 调度器在性能、可靠性和灵活性方面都得到了显著提升,能够更好地适应现代硬件和工作负载。
原理:修正了某些 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 系统的 CPU 不变性状态发生变化时,重新构建调度域以适应新的硬件特性,确保调度器能够正确感知系统的拓扑结构。
场景:适用于 ARM64 系统,特别是那些 CPU 特性可能动态变化的系统,如某些节能模式下的处理器。
效果:提高了 ARM64 系统的调度效率和性能,确保调度器能够根据最新的硬件状态做出最优的调度决策。
补丁:ecec9e86d1a3 arm64: Rebuild sched domains on invariance status changes
原理:改进了调度器对每 CPU 内核线程唤醒任务的检测逻辑,确保正确识别由内核线程唤醒的任务,避免调度决策错误。
场景:适用于有大量内核线程活动的系统,如 I/O 密集型应用、网络服务器等。
效果:提高了内核线程唤醒的准确性和性能,确保被内核线程唤醒的任务能够得到及时的调度处理,减少了调度延迟。
补丁:8b4e74ccb582 sched/fair: Fix detection of per-CPU kthreads waking a task
原理:重构了 schedstats 相关代码,使其不再依赖于公平调度类,为其他调度类使用 schedstats 提供了便利。
场景:适用于需要在不同调度类中使用统计功能的场景,特别是在开发新调度类或扩展现有调度类时。
效果:提高了代码的可维护性和扩展性,为调度器的进一步发展奠定了基础,同时也使得不同调度类能够更方便地利用统计功能进行性能分析。
补丁:60f2415e19d3 sched: Make schedstats helpers independent of fair sched class
原理:将 sched_statistics 结构从公平调度类中分离出来,使其可以被其他调度类使用,提高了代码的模块化程度。
场景:适用于多调度类共存的系统,特别是在需要统一统计接口的场景下。
效果:提高了代码的模块化程度,为调度器的扩展提供了更大的灵活性,使得不同调度类能够共享统计基础设施。
补丁:ceeadb83aea2 sched: Make struct sched_statistics independent of fair sched class
原理:解决了内存上下文 ID(mm_cid)管理中导致的性能问题,修复了由 mm_cid 引入的性能回归。
场景:适用于内存密集型工作负载,特别是在多进程、多线程环境下的内存操作。
效果:恢复了系统性能,特别是在内存密集型工作负载下,减少了内存上下文切换的开销,提高了系统的整体吞吐量。
补丁:223baf9d17f2 sched: Fix performance regression introduced by mm_cid
原理:交错 CFS(完全公平调度器)带宽定时器的执行,减少定时器开销,提高低系统负载下单线程应用的性能。
场景:适用于低系统负载下运行单线程应用的场景,如桌面环境、轻量级服务器等。
效果:提高了低系统负载下单线程应用的性能,减少了定时器对应用执行的干扰,使得单线程应用能够获得更连贯的 CPU 时间片。
补丁:41abdba93747 sched: Interleave cfs bandwidth timers for improved single thread performance at low utilization
原理:移除了 drm_sched_dependency_optimized,简化了 DRM(直接渲染管理器)调度器的依赖管理,提高了调度器的效率。
场景:适用于图形处理、视频渲染等需要 DRM 调度器的场景,特别是在高帧率、高分辨率的图形应用中。
效果:提高了 DRM 调度器的效率和可维护性,减少了调度开销,使得图形处理能够更流畅地进行。
补丁:2cf9886e2816 drm/scheduler: remove drm_sched_dependency_optimized
原理:重新设计了 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
原理:在 switch_mm_cid() 中添加了缺失的内存屏障,确保内存上下文 ID 的更新能够被正确地同步到所有 CPU。
场景:适用于多处理器系统,特别是在频繁切换内存上下文的场景下。
效果:提高了 mm_cid 操作的可靠性,避免了因内存屏障缺失导致的潜在一致性问题,确保了系统的稳定性。
补丁:fe90f3967bdb sched: Add missing memory barrier in switch_mm_cid
原理:引入了全新的可扩展调度器框架,允许使用 BPF 程序定义自定义调度策略,无需修改内核即可实现调度器创新。
场景:适用于需要定制调度策略的场景,如特定工作负载优化、实时应用、高性能计算等。
效果:允许针对特定工作负载定制调度策略,提高性能;减少了内核修改的需要,通过 BPF 程序即可实现调度器创新;为调度器的发展提供了更大的灵活性。
补丁:f0e1a0643a59 sched_ext: Implement BPF extensible scheduler class
原理:优化了 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 中默认空闲 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
原理:优化了 topology_span_sane 函数的实现,减少了不必要的计算,提高了拓扑扫描的速度。
场景:适用于大型 NUMA 系统,特别是在需要频繁进行拓扑扫描的场景下。
效果:加快了调度器的拓扑感知速度,减少了调度决策的延迟,使得调度器能够更快速地适应系统拓扑结构的变化。
补丁:f55dac1dafb3 sched/topology: improve topology_span_sane speed
原理:移除了 mm_cid_get() 中未使用的代码,简化了代码结构,提高了可维护性。
场景:适用于所有使用 mm_cid 的系统,特别是在代码维护和审计时。
效果:提高了代码的可维护性,减少了代码复杂度,便于后续的性能优化和 bug 修复。
补丁:53abe3e1c154 sched: Remove never used code in mm_cid_get()
原理:进一步限制了调度器的抢占模式,确保抢占操作能够更加安全和可预测。
场景:适用于实时应用、低延迟场景,特别是对抢占行为敏感的应用。
效果:提高了系统的稳定性和可预测性,减少了因抢占导致的潜在问题,确保了关键任务的执行时间。
补丁:7dadeaa6e851 sched: Further restrict the preemption modes
原理:为 sched_ext 中的 dsq(dispatch queue)创建失败添加了错误日志,提高了调试能力。
场景:适用于使用 sched_ext 的系统,特别是在调试和故障排查时。
效果:提高了系统的可调试性,使得 sched_ext 的问题能够被更快速地识别和解决。
补丁:2f8d489897ae sched_ext: Add error logging for dsq creation failures
原理:为剩余调度器中的 dsq 创建失败添加了错误日志,提高了工具的调试能力。
场景:适用于使用 sched_ext 工具的系统,特别是在开发和测试新调度策略时。
效果:提高了工具的可调试性,使得 sched_ext 工具的问题能够被更快速地识别和解决。
补丁:bd4f0822f4ec tools/sched_ext: Add error logging for dsq creation failures in remaining schedulers
sched_ext 是一个革命性的调度器框架,它通过以下方式实现了高度可扩展性:
| 优化特性 | 性能提升 | 适用场景 | 技术收益 |
|---|---|---|---|
| sched_ext 框架 | 高 | 特定工作负载、定制化调度需求 | 灵活的调度策略定制,针对特定工作负载的性能优化 |
| 拓扑扫描优化 | 中 | 大型 NUMA 系统 | 加快拓扑感知速度,减少调度延迟 |
| RSEQ 缓存局部性优化 | 中 | 间歇性工作负载、使用 RSEQ 的应用 | 减少缓存开销,提高应用性能 |
| 唤醒同步行为优化 | 中 | 多线程应用 | 减少唤醒延迟,提高线程协作性能 |
| 内存分配优化 | 低到中 | 实时应用、低延迟场景 | 提高调度器实时性,减少延迟 |
| CFS 带宽定时器交错 | 低到中 | 低系统负载下的单线程应用 | 提高低负载下单线程性能 |
| schedutil 性能估计改进 | 中 | 所有场景 | 优化 CPU 频率调节,提高能耗效率 |
| AMD CPPC 修复 | 中 | AMD Ryzen 系统 | 提高处理器性能利用率 |
从 Linux 5.10 到最新版本(7.0-rc2),调度器领域经历了重大创新和改进,特别是 sched_ext 框架的引入,为 Linux 调度器带来了前所未有的灵活性和可扩展性。这些优化不仅提高了调度器的性能,还为特定工作负载的定制化调度策略提供了可能。
主要的性能提升来自于:
这些优化使得 Linux 调度器能够更好地适应现代硬件和工作负载,为各种应用场景提供了更好的性能和可靠性。未来,随着 sched_ext 生态的发展,我们可以期待看到更多针对特定工作负载的优化调度策略,进一步提升 Linux 系统的性能和可靠性。