我正在尝试测量正在运行的进程的磁盘 IO 延迟以制作直方图。
我可以在提供 DTrace 的操作系统中使用 DTrace 来做到这一点(例如,这篇 Joyent 论文),但我的应用程序在 Linux 中运行。我的第一个想法是尝试perf
,我可以得到计数器,但我找不到任何方法来获取时间增量。我可以使用strace
(例如)获得时间增量strace -e read -T
,但我不确定是否可以将跟踪限制为磁盘IO(该系统也有一个繁忙的网络接口)。
在Linux下有什么办法可以做到这一点吗?
答案1
这其实很复杂。但有提示:
了解 SystemTap,这是 DTrace 的 Linux 模拟。我认为他们甚至可能有类似任务的示例脚本。
学习块跟踪。理论上,您也许能够解析它的输出。这将比设备延迟(服务时间)更长响应时间节目上车
read()
。
是strace
可能不合适,因为它会跟踪所有内容(所有系统调用,即使您使用-e
过滤器)并且会加载服务器并显着减慢进程。Perf
是一个非常晦涩的工具,您可能有时会认为自己理解了它的输出,但实际上并没有,而且它的功能集高度依赖于内核版本。基本上目前perf
适合测量中央处理器时间(周期),并且[但]不适合测量响应时间(你实际上需要的)。我听说他们想要实现一些东西来缓解这个问题,所以在最近开发的内核上可能会有一些东西。 (perf script -l
如果您想进一步调查,还可以查看 perf-scripts ( )。)
也许你能从中得到一些东西追踪。阅读这篇文章http://lwn.net/Articles/370423/(这对于介绍.) 正如我所看到的,您可以通过
pid
和 函数来限制 ftracing,然后使用类似sys_read
.我试过这个作为例子给你:# mount -t debugfs debugfs /sys/kernel/debug # if it's not already mounted # cd /sys/kernel/debug/tracing # echo $$ > set_ftrace_pid # pid of process to trace # echo sys_read sys_write > set_ftrace_filter # echo function_graph > current_tracer # head trace # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | 0) 8.235 us | sys_write(); 0) 3.393 us | sys_write(); 0) ! 459859.3 us | sys_read(); 0) 6.289 us | sys_write(); 0) 8.773 us | sys_write(); 0) ! 1576469 us | sys_read();
答案2
如果您只对块设备的“读”或“写”调用数量感兴趣这是红帽的 SOP,用于确定。
使用块转储功能和一些脚本,可以收集有关正在生成的 I/O 操作过程的高级概述。为此,请完成以下操作:
短时间内禁用系统日志记录(这样就不会妨碍数据捕获):
# 服务 syslog 停止 # echo 1 > /proc/sys/vm/block_dump
等待高 iowait 问题发生,一旦重新启用 syslog(或 rsyslog,如果使用它),并禁用块转储:
# 服务系统日志启动 # echo 0 > /proc/sys/vm/block_dump
使用以下命令解析 dmesg 输出以查找某些进程发出的读/写/脏操作:
# dmesg | awk '/(READ|WRITE|dirtied)/ {activity[$1]++} END {for (x in Activity) print x, Activity[x]}'|排序-nr -k 2,2|头 -n 10
kjournald(1425): 5984 kjournald(3681): 1269 pdflush(27301): 725 iostat(2913): 134 crond(26919): 61 crond(28985): 60 crond(7026): 54 sshd(28175): 50 ( 15388): 50 鹦鹉螺(24498): 46
上面的示例输出显示了在块转储运行期间发出 READ、WRITE 和脏操作的前 10 个进程。使用此数据可以收集正在发出的操作进程数量的高级概述,并且可以帮助确定单个进程是否对 iowait 贡献很大。
还有一些命令行工具,例如 atop 和 iotop,可以为您提供每个进程的 iowait 统计信息,并且可以作为脚本的一部分运行(这意味着它们具有批处理模式,可以对特定 PID 进行单次迭代)。
编辑: 做更多研究看起来你可以从 /proc/$pid/stat 获取每个进程的 iowait(搜索“聚合块 I/O 延迟”)