这是我昨晚在硅谷 Linux 技术聚会上演示的一些新开源工具的快速浏览。这些使用最近 Linux 中添加的新 eBPF 功能,包括 Linux 4.3。
总结磁盘I/O延迟的分布:
# ./biolatency
跟踪块设备 I/O... 按 Ctrl-C 结束。
^C
usecs:计数分布
0 -> 1 : 0 | |
2 -> 3 : 0 | |
4 -> 7 : 0 | |
8 -> 15 : 0 | |
16 -> 31 : 0 | |
32 -> 63 : 0 | |
64 -> 127 : 1 | |
128 -> 255 : 12 |******** |
256 -> 511 : 15 |********** |
512 -> 1023 : 43 |************************************|
1024 -> 2047 : 52 |******************************************|
2048 -> 4095 : 47 |**********************************|
4096 -> 8191 : 52 |******************************************|
8192 -> 16383 : 36 |************************** |
16384 -> 32767 : 15 |********** |
32768 -> 65535 : 2 |* |
65536 -> 131071 : 2 |* |
跟踪每个磁盘的 I/O:
# ./biosnoop
TIME(s) COMM PID 磁盘 T 扇区字节 LAT(ms)
0.000004001 监督 1950 xvda1 W 13092560 4096 0.74
0.000178002 监督 1950 xvda1 W 13092432 4096 0.61
0.001469001 监督 1956 xvda1 W 13092440 4096 1.24
0.001588002 监督 1956 xvda1 W 13115128 4096 1.09
1.022346001 监督 1950 xvda1 W 13115272 4096 0.98
1.022568002 监督 1950 xvda1 W 13188496 4096 0.93
1.023534000 监督 1956 xvda1 W 13188520 4096 0.79
1.023585003 监督 1956 xvda1 W 13189512 4096 0.60
跟踪 open() 系统调用:
# ./opensnoop
PID COMM FD ERR 路径
17326 <...> 7 0 /sys/kernel/debug/tracing/trace_pipe
17358 运行 3 0 /lib/x86_64-linux-gnu/libtinfo.so.5
17358 run 3 0 /lib/x86_64-linux-gnu/libdl.so.2
17358 run 3 0 /lib/x86_64-linux-gnu/libc.so.6
17358 run -1 6 /dev/tty
17358 run 3 0 /proc/meminfo
17358 run 3 0 /etc/nsswitch.conf
Counting VFS operation types:
# ./vfsstat
TIME READ/s WRITE/s CREATE/s OPEN/s FSYNC/s
18:35:35: 241 15 4 99 0
18:35:36: 232 10 4 98 0
18:35:37: 244 10 4 107 0
18:35:38: 235 13 4 97 0
18:35:39: 6749 2633 4 1446 0
18:35:40: 277 31 4 115 0
计算每秒匹配“tcpsend”的内核函数调用:
# ./funccount -i 1 'tcp*send*'
Tracing... Ctrl-C to end.
ADDR FUNC COUNT
ffffffff816d2281 tcp_send_delayed_ack 30
ffffffff816d6c81 tcp_v4_send_check 31
ffffffff816c2f61 tcp_sendmsg 31
ffffffff816bf851 tcp_send_mss 31
ADDR FUNC COUNT
ffffffff816d1db1 tcp_send_fin 3
ffffffff816d0f71 tcp_send_ack 18
ffffffff816d2281 tcp_send_delayed_ack 214
ffffffff816c2f61 tcp_sendmsg 231
ffffffff816bf851 tcp_send_mss 231
ffffffff816d6c81 tcp_v4_send_check 255
ADDR FUNC COUNT
ffffffff816d0f71 tcp_send_ack 2
ffffffff816d2281 tcp_send_delayed_ack 9
ffffffff816c2f61 tcp_sendmsg 30
ffffffff816bf851 tcp_send_mss 30
计时 tcp_sendmsg() 延迟(调用持续时间),以微秒为单位:
# ./funclatency -u tcp_sendmsg
Tracing tcp_sendmsg... Hit Ctrl-C to end.
^C
usecs : count distribution
0 -> 1 : 20778 |**************************************|
2 -> 3 : 15429 |**************************** |
4 -> 7 : 355 | |
8 -> 15 : 171 | |
16 -> 31 : 106 | |
32 -> 63 : 9 | |
分离…
…所有这些工具都有手册页,并且大多数还有帮助信息:
# ./funclatency -h
usage: funclatency [-h] [-p PID] [-i INTERVAL] [-T] [-u] [-m] [-r] pattern
时间核函数和打印延迟作为直方图
位置参数:
pattern search expression for kernel functions
optional arguments:
-h, --help show this help message and exit
-p PID, --pid PID trace this PID only
-i INTERVAL, --interval INTERVAL
summary interval, seconds
-T, --timestamp include timestamp on output
-u, --microseconds microsecond histogram
-m, --milliseconds millisecond histogram
-r, --regexp use regular expressions. Default is "*" wildcards
only.
examples:
./funclatency do_sys_open # time the do_sys_open() kenel function
./funclatency -u vfs_read # time vfs_read(), in microseconds
./funclatency -m do_nanosleep # time do_nanosleep(), in milliseconds
./funclatency -mTi 5 vfs_read # output every 5 seconds, with timestamps
./funclatency -p 181 vfs_read # time process 181 only
./funclatency 'vfs_fstat*' # time both vfs_fstat() and vfs_fstatat()
Linux 4.3+, eBPF
Linux 4.3 中的新功能是能够从 Extended Berkeley Packet Filters (eBPF) 程序打印字符串。这只是一个小的补充,但我需要许多工具。 eBPF 是一个虚拟机,用于运行用户定义的沙盒字节码,并带有用于数据存储的映射。我在 eBPF 中写过它:一小步。
eBPF 增强了 Linux Tracing,允许小程序在 Tracing 事件上执行。在我上面的工具中,eBPF 让我可以使用自定义时间戳标记事件、存储直方图、过滤事件,并且只将汇总信息发送到用户级别。这些功能以尽可能低的间接成本为我提供了我想要的信息。
虽然 eBPF 提供了惊人的超能力,但有一个问题:很难通过其汇编或 C 接口使用。挑战吸引了我,但它可能是一种残酷的体验,尤其是如果您直接编写 eBPF 程序集(例如,请参见 sock_example.c 中的 bpf_insn_prog;我还没有从头开始编写其中一个可以编译的代码)。 C 接口更好(参见 samples/bpf 中的其他示例),但它仍然很费力且难以使用。
输入密件抄送
BPF Compiler Collection (bcc) 项目为 eBPF 提供了一个前端,使编写程序更加容易。它使用 C 作为后端工具,使用 Python 作为前端接口。我在本文开头的工具都使用了bcc,可以在github上bcc的工具目录中找到。还浏览该目录以查找 _example.txt 文件。
我修改了右侧的图表(来自 Velocity 2015)以显示 bcc 所扮演的角色:它提高了 eBPF 的可用性。
密件抄送还处于早期阶段,现在设置和使用并不容易,即使您使用的是 Linux 4.3+(例如,这里是我自己的笔记)。将来,这应该像添加包一样简单。这将只添加用户级软件:内核部分(eBPF)已经在 Linux 内核中。
就像 bcc 的一个示例一样,这是我的biolatency tool的完整代码,我在这篇文章的顶部展示了它:
很多代码是处理命令行参数的逻辑。C 检测代码以 bpf_text 的形式在线定义。我想改进一些事情,比如切换到跟踪点而不是 kprobes,但到目前为止这还不错。我可以在其中编写工具。
bcc 还可以比我这里的示例做更多的事情:它也可以用于高级网络流量控制。有关这些功能的更多信息,请参阅IO Visor项目。
即使很少有人学习 bcc 编程,它也应该通过使用它的工具看到成功。在像 Netflix 这样的公司,只需我们几个人学习 bcc/eBPF 就可以对公司产生重大影响:我们可以开发工具供其他人使用,并为我们的其他分析软件(例如Vector)开发插件。我们创造的很多东西都是开源的,所以其他人也会受益。
其他示踪剂和工具
bcc 不会是 eBPF 的唯一接口。已经有将其引入 Linux perf_events 的工作。很高兴看到带有语法的跟踪器(如 SystemTap 或 ktap)支持 eBPF,这将使临时工具更容易编写。(也许 bcc 将来会提供自己的语法。)eBPF 应该使其他跟踪器的其他增强成为可能。
我之前创建了perf-tools,这是一个用于 Linux 系统的主要基于 ftrace 的跟踪工具的集合。使用 eBPF 和 bcc,我最终会将其中一些工具切换到 eBPF,在那里它们将具有更多功能,更易于维护,并且开销更低。例如,我的 perf-tools iolatency工具,相当于 biolatency,在用户级别处理每个磁盘事件,花费了可衡量的开销(我在工具及其手册页中警告过)。bcc biolatency 版本的开销应该可以忽略不计。
使用 bcc/eBPF,我还将创建许多以前不可能(或不切实际)做的新工具。
感谢 PLUMgrid 的 Alexei Starovoitov 和 Brenden Blanco 以及其他人开发 eBPF 和 bcc,以及 Deirdré Straughan 对这篇文章的编辑。
转载翻译自: https://www.brendangregg.com