我一直在尝试在 perf 上启用上下文切换事件,并使用 perf 脚本的 perf.data 转储来调查线程阻塞时间。
到目前为止,唯一两个似乎有用的记录选项是上下文切换和所有计划事件。
这是我在 perf 上运行的命令:
perf record -g -a -F 999 -e cpu-clock,sched:sched_stat_sleep,sched:sched_switch,sched:sched_process_exit,context-switches
然而,两者似乎都不完整,通常 sched_switch 事件看起来像这样:
comm1 0/0 [000] 0.0: 1 sched:sched_switch: prev_comm=comm1 prev_pid=0 prev_prio=0 prev_state=S ==> next_comm=comm2 next_pid=1 next_prio=1
stacktrace...
根据我的理解,prev_comm始终是要被阻塞的线程,而next_comm是要被解除阻塞的线程。这是一个正确的假设吗?如果是,我似乎无法获得有关事件的完整数据,因为有许多线程在 prev_comm 上被阻止,但似乎从未获得相应的 next_comm。
启用上下文切换似乎没有多大作用,因为没有有关线程被阻塞或解除阻塞的信息(除非我完全遗漏了一些东西,我希望能解释它们如何工作)。
典型的上下文切换事件如下所示:
comm1 0/0 [000] 0.0: 1 context-switch:
stacktrace...
tl;dr,如何通过 perf 脚本的输出在 Linux 上进行阻塞时间调查以及需要在 perf 记录上启用哪些选项?
谢谢。
答案1
我知道这个问题已经很老了(2 月 16 日),但这里有一个回复,以防对其他人有帮助。问题在于您输入了“-F 999”,表示您希望以每秒 999 次的频率对事件进行采样。对于“跟踪”事件,您通常不想进行采样。例如,当我选择 sched:sched_switch 时,我想查看每个上下文切换。如果您输入 -F 999 那么您将获得上下文切换的样本...如果您使用以下内容查看“perf record”cmd 的输出:
perf script --verbose -I --header -i perf.dat -F comm,pid,tid,cpu,time,period,event,trace,ip,sym,dso > perf.txt
那么您会看到“句点”(时间戳和事件名称之间的数字)(通常)不会 == 1。
如果您使用如下所示的“perf record”cmd,您将在“perf script”输出中看到一个周期 1,如下所示:
Binder:695_5 695/2077 [000] 16231.700440: 1 sched:sched_switch: prev_comm=Binder:695_5 prev_pid=2077 prev_prio=120 prev_state=S ==> next_comm=kworker/u16:17 next_pid=7665 next_prio=120
一个冗长的解释,但基本上是:不要这样做(其中“that”是“-F 999”)。
如果你只是做类似的事情:
perf record -a -g -e sched:sched_switch -e sched:sched_blocked_reason -e sched:sched_stat_sleep -e sched:sched_stat_wait sleep 5
那么输出将显示每个上下文切换以及每个事件的调用堆栈。你可能需要这样做:
echo 1 > /proc/sys/kernel/sched_schedstats
获取 sched_stat 事件。