如何获取带时间戳的Linux CPU调度事件?进程调度统计方案咨询
解决方案:计算进程就绪到调度的时长及期间调度进程数
一、现成工具推荐
- perf:Linux原生性能分析工具,可精准追踪调度事件。执行
perf record -e sched:sched_wakeup,sched:sched_switch记录目标场景的调度数据,再用perf script解析输出,通过关联目标进程的sched_wakeup(进入就绪态)和sched_switch(被CPU调度)事件时间戳,计算就绪延迟;同时统计期间sched_switch事件中其他进程的调度次数。 - ftrace:内核内置追踪框架,安全且性能开销可控。用
trace-cmd record -e sched_wakeup -e sched_switch采集事件,停止后执行trace-cmd report筛选目标进程的事件流,手动或通过脚本计算时间差,统计期间其他进程的调度次数。 - bpftrace:基于eBPF的动态追踪工具,无需修改内核,性能影响极小。可编写极简脚本直接输出所需指标:
运行时指定目标PID:#!/usr/bin/bpftrace BEGIN { printf("PID\t唤醒时间(ns)\t调度时间(ns)\t就绪延迟(ns)\t期间调度其他进程数\n"); } tracepoint:sched:sched_wakeup { if (args->pid == $1) { @wakeup[args->pid] = nsecs; @count[args->pid] = 0; } } tracepoint:sched:sched_switch { if (@wakeup[$1] && args->next_pid != $1) { @count[$1]++; } if (args->next_pid == $1 && @wakeup[$1]) { $latency = nsecs - @wakeup[$1]; printf("%d\t%d\t%d\t%d\t%d\n", $1, @wakeup[$1], nsecs, $latency, @count[$1]); delete(@wakeup[$1]); delete(@count[$1]); } }bpftrace script.bt <目标进程PID>,直接得到计算结果。
二、直接修改内核的问题分析
你之前用printk修改内核出现性能问题甚至死锁,核心原因:
- 调度路径属于内核临界区,
printk会尝试获取控制台锁,容易与调度逻辑持有的内核锁形成锁竞争,触发死锁。 - 高频
printk会产生大量日志输出,占用CPU和IO资源,严重拖慢系统性能。
三、自定义开发的替代方案(不推荐)
若现成工具无法满足需求,优先选择eBPF程序替代直接修改内核:
- eBPF程序运行在内核态但有安全隔离机制,不会破坏内核稳定性,性能开销远低于硬编码
printk。 - 通过eBPF追踪点或kprobe捕获
sched_wakeup和sched_switch事件,在用户态处理数据并计算指标,无需修改内核源码。
内容的提问来源于stack exchange,提问作者Senith Uthsara
相关产品推荐
相关产品推荐

