4. perf sched子命令概览

perf sched 是 perf 工具集中专用于进程调度延迟分析的子命令集合。它通过内核 tracepoint 捕获调度事件,提供从数据采集、延迟量化到可视化回放的全链路分析能力。本节将逐一介绍 perf sched record、latency、map、replay、diff 等核心子命令的功能定义、输出格式与典型适用场景。

4.1 子命令全景图

以下 SVG 展示了 perf sched 子命令的完整工作流与数据流向关系:

perf sched 子命令全景图 perf sched 子命令全景图 perf sched record perf.data perf sched latency perf sched map perf sched replay perf sched diff 调度延迟统计表 时间轴上下文切换图 调度过程模拟回放 两次实验差异对比 record 采集 → 四种分析视角 → 定位调度延迟根因

4.2 子命令功能详解

4.2.1 perf sched record — 调度事件采集

该子命令是调度分析的起点,通过启用调度器相关的 tracepoint 事件来记录进程的创建、唤醒、切换和迁移行为。默认采集的事件包括:

  • sched:sched_switch — 进程上下文切换
  • sched:sched_wakeup / sched:sched_wakeup_new — 进程唤醒
  • sched:sched_migrate_task — 进程跨 CPU 迁移
  • sched:sched_process_fork / sched:sched_process_exit — 进程创建与退出

典型用法:

# 采集 10 秒调度事件,默认输出到 perf.data
perf sched record -- sleep 10

# 指定输出文件,便于后续对比
perf sched record -o sched_A.data -- stress --cpu 4 --timeout 5
适用场景:任何调度延迟分析的起点。建议在负载稳定后采集 30 秒以上数据,避免冷启动噪声。采集期间应避免 perf 自身被调度出去,可考虑绑定到隔离 CPU。

4.2.2 perf sched latency — 调度延迟统计

该子命令解析 perf.data,计算每个进程的调度延迟指标,并以表格形式输出。核心指标包括:

指标 含义 单位
wait-time 进程从被唤醒到获得 CPU 的平均等待时间 ms
sch-delay 调度器决策延迟(从唤醒到调度器选择该进程) ms
run-delay 进程就绪但未运行的时间(含等待队列排队) ms
max-delay 单次调度延迟最大值 ms

典型用法:

# 输出所有进程的调度延迟统计
perf sched latency

# 按延迟降序排列,快速定位异常进程
perf sched latency --sort max
输出解读要点:重点关注 wait-time 和 max-delay 偏高的进程。若某进程的 max-delay 超过 10ms,通常意味着存在调度延迟问题。结合 --sort max 可快速锁定最差进程。

4.2.3 perf sched map — 时间轴上下文切换可视化

该子命令将调度事件转换为基于时间轴的 ASCII 图表,展示每个 CPU 上运行的进程随时间的变化。每一列代表一个时间片,每一行代表一个 CPU 核心,字符表示在该时间片内运行的进程名称缩写。

典型用法:

# 生成上下文切换时间轴
perf sched map

# 指定时间窗口,聚焦问题区间
perf sched map --time 2.0,5.0

输出示例(示意):

  *A0                   A0                   B1
  *.                   .                   .
  .  *B1                B1                   C2
  .  .                  .                    .
  .  .  *C2             C2                   A0
  -------------------------------------------------
  CPU0  CPU1  CPU2  CPU3  CPU4  CPU5  CPU6  CPU7
适用场景:当 latency 报告显示某进程延迟异常时,使用 map 查看该进程在时间轴上的实际调度序列,判断是否存在 CPU 负载不均、频繁迁移或优先级反转。

4.2.4 perf sched replay — 调度过程模拟回放

该子命令将采集到的调度事件重新模拟执行,测量在理想条件下(无外部干扰)的调度延迟,并与实际采集的延迟进行对比。它通过重放调度序列来评估调度器本身的效率。

典型用法:

# 执行调度回放,输出模拟延迟
perf sched replay

# 指定回放次数,取平均结果
perf sched replay --repeat 3

输出关键字段:

字段 说明
nr_run_events 回放过程中处理的调度事件总数
nr_sleep_events 进程睡眠事件数
nr_wakeup_events 进程唤醒事件数
target-less wakeups 无明确目标 CPU 的唤醒次数(可能暗示负载均衡问题)
average delay 回放模拟的平均调度延迟
注意事项:回放结果依赖于采集时的调度序列,如果系统负载在采集期间剧烈变化,回放结果可能与实际偏差较大。建议在稳定负载下采集数据,并多次回放取均值。

4.2.5 perf sched diff — 两次实验差异对比

该子命令对比两次 perf sched latency 的输出结果,生成差异报告。常用于验证调优措施的效果,例如对比调优前后的调度延迟变化。

典型用法:

# 对比调优前后的延迟数据
perf sched diff perf_before.data perf_after.data

# 只显示变化超过 5% 的进程
perf sched diff --percentage 5 perf_before.data perf_after.data

输出格式示例:

#              wait-time (ms)          sch-delay (ms)         run-delay (ms)
# process      before  after  diff     before  after  diff    before  after  diff
stress-1234    2.34    1.12   -52.1%   1.87    0.95   -49.2%  3.21    1.45   -54.8%
kworker-56     0.45    0.48   +6.7%    0.32    0.35   +9.4%   0.78    0.82   +5.1%
最佳实践:在进行内核参数调优(如 kernel.sched_min_granularity_ns、kernel.sched_wakeup_granularity_ns)前后各采集一次数据,使用 diff 子命令量化调优效果。重点关注 wait-time 和 max-delay 的变化百分比。

4.3 子命令适用场景速查表

子命令 核心输出 典型场景
record 原始调度事件数据文件 所有调度分析的起点;采集生产或测试负载的调度轨迹
latency 进程级调度延迟统计表 快速定位延迟异常的进程;量化平均/最大等待时间
map 时间轴上下文切换图 可视化分析 CPU 负载分布、进程迁移模式、优先级调度行为
replay 模拟回放延迟报告 评估调度器自身效率;排除外部干扰后的理想延迟测量
diff 两次实验的延迟差异对比 调优前后效果验证;内核版本或配置变更的影响评估

4.4 组合使用示例:从采集到定位

以下流程展示如何组合使用 perf sched 子命令完成一次完整的调度延迟分析:

  1. 采集基线数据:perf sched record -o baseline.data -- sleep 30
  2. 生成延迟统计:perf sched latency -i baseline.data --sort max,发现 nginx-1234 的 max-delay 达到 15ms。
  3. 可视化调度序列:perf sched map -i baseline.data --time 5.0,10.0,观察到 nginx-1234 在 CPU2 和 CPU3 之间频繁迁移。
  4. 模拟回放验证:perf sched replay -i baseline.data,确认模拟延迟仅为 2ms,说明延迟主要由外部因素(如中断、其他进程争抢)导致。
  5. 调优后对比:调整 kernel.sched_migration_cost_ns 后再次采集 perf sched record -o tuned.data -- sleep 30,执行 perf sched diff baseline.data tuned.data 验证改善效果。
效率提示:日常分析中,latency 和 map 是最常用的组合。先通过 latency 锁定异常进程,再用 map 观察其调度行为,通常能快速定位 80% 的调度延迟问题。