4、负载均衡触发时机:周期性负载均衡(tick)、空闲时负载均衡(newidle)、唤醒时负载均衡(wake)、fork/exec时负载均衡
Linux 调度器的负载均衡并非持续运行,而是在特定事件或时间点被触发。理解这四种触发时机,是调试跨 CPU 域迁移与负载均衡协同工作的基础。每种触发时机对应不同的系统状态和性能目标,错误的参数配置可能导致负载失衡或额外的迁移开销。
4.1 四种触发时机总览
下表从触发条件、主要目标、典型开销和适用场景四个维度,对比了四种负载均衡触发时机:
| 触发时机 | 触发条件 | 主要目标 | 典型开销 | 适用场景 |
|---|---|---|---|---|
| 周期性负载均衡(tick) | 每个调度 tick(通常 1ms~4ms) | 长期全局负载均衡 | 中等,随 CPU 数量增加 | 通用服务器、长时间运行任务 |
| 空闲时负载均衡(newidle) | CPU 即将进入空闲状态 | 快速拉取任务,避免 CPU 空转 | 低,但可能延迟空闲 | 交互式系统、延迟敏感负载 |
| 唤醒时负载均衡(wake) | 任务从睡眠状态被唤醒 | 减少跨域唤醒延迟 | 低,仅检查目标 CPU | 短任务、IPC 密集型应用 |
| fork/exec 时负载均衡 | 新进程创建或执行新程序 | 初始放置,避免后续迁移 | 低,仅一次放置决策 | 批处理、容器启动、Web 服务器 |
4.2 周期性负载均衡(tick)
周期性负载均衡是调度器最基础的均衡机制。每次时钟 tick 中断时,当前 CPU 会检查是否需要发起负载均衡。该机制由 sched_tick() 函数驱动,通过 load_balance() 执行。
kernel.sched_migration_cost_ns:任务迁移的“成本”时间窗口,默认 500000 ns。若任务运行时间小于此值,则视为“热缓存”任务,避免迁移。kernel.sched_nr_migrate:一次均衡操作最多迁移的任务数,默认 32。
周期性均衡的触发频率由 sysctl_sched_interval 控制,默认值为 1ms(HZ=1000 时)。每次 tick 仅检查当前 CPU 所属调度域是否需要均衡,不会全局扫描所有域。
4.3 空闲时负载均衡(newidle)
当 CPU 执行完所有 runqueue 中的任务,即将进入 idle 状态时,会触发 newidle 均衡。这是降低 CPU 空转率、提高系统吞吐量的关键机制。其核心函数为 newidle_balance()。
kernel.sched_migration_cost_ns 在此处同样生效。
newidle 均衡的搜索范围受 SD_BALANCE_NEWIDLE 标志控制。如果某个调度域未设置此标志,则 newidle 均衡不会扫描该域。
4.4 唤醒时负载均衡(wake)
当任务从睡眠状态被唤醒时,调度器会执行 wake 均衡,决定将任务放置到哪个 CPU 上。这由 select_task_rq_fair() 函数处理,并受 SD_BALANCE_WAKE 标志控制。
wake 均衡的核心目标是减少跨域唤醒延迟。如果唤醒源 CPU 和目标 CPU 不在同一个调度域,调度器会评估是否将任务迁移到唤醒源所在的 CPU 或域内其他空闲 CPU。
/proc/sys/kernel/sched_wakeup_granularity_ns 设置过大,wake 均衡可能无法及时将任务迁移到更优的 CPU,导致唤醒延迟增加。该参数默认值为 4ms(HZ=250 时),建议在低延迟场景下调小。
wake 均衡的决策逻辑可概括为:
- 检查缓存亲和性:如果任务上次运行的 CPU 仍在同一域且负载不高,优先放置。
- 评估域负载:比较唤醒源 CPU 所在域与目标 CPU 所在域的负载差异。
- 执行迁移:若跨域迁移收益大于成本,则通过
migrate_task()移动任务。
4.5 fork/exec 时负载均衡
当新进程通过 fork() 创建或通过 exec() 加载新程序时,调度器会执行 fork/exec 均衡,为新任务选择初始 CPU。这是任务生命周期中第一次负载均衡决策,直接影响后续的缓存热度和迁移开销。
该机制由 sched_fork() 和 sched_exec() 函数实现,受 SD_BALANCE_FORK 和 SD_BALANCE_EXEC 标志控制。
| 事件 | 触发函数 | 均衡策略 | 典型参数影响 |
|---|---|---|---|
| fork | sched_fork() |
选择负载最低的 CPU,尽量与父进程同域 | kernel.sched_child_runs_first(子进程优先运行) |
| exec | sched_exec() |
重新评估 CPU 负载,可能迁移到更空闲的 CPU | kernel.sched_autogroup_enabled(自动分组影响放置) |
SD_BALANCE_FORK 未正确配置,所有子进程可能堆积在同一 CPU 上,导致负载不均。建议通过 taskset 或 cgroup cpuset 配合调度域参数进行调优。
4.6 四种触发时机的协同关系
在实际运行中,四种触发时机并非独立工作,而是形成一套完整的负载均衡体系:
- fork/exec 均衡 负责初始放置,减少后续迁移需求。
- wake 均衡 在任务唤醒时微调放置位置,适应瞬时负载变化。
- tick 均衡 作为后台守护机制,定期纠正长期负载偏差。
- newidle 均衡 作为最后手段,在 CPU 空闲时主动拉取任务,最大化利用率。
perf stat -e sched:sched_migrate_task 统计迁移次数,判断哪种触发时机导致的迁移最多。然后针对性地调整对应参数,例如减少 tick 均衡频率(增大 sysctl_sched_interval)或关闭某些域的 newidle 均衡。