如何追踪追踪程序

如何追踪追踪程序

概述: 就是如何去追踪自己写的ebpf程序的性能。举个例子,你写了一个ebpf程序,想要将其附加到内核函数后,看看内核函数的延迟变大了多少。

说明: 本文章以测试tcp_v4_send_reset()函数延迟为例子,我们可以知道tcp_send_reset()本身是作为一个tracepoint的,而且tcp_v4_send_reset()会调用它。所以我们将epbf程序通过tracepoint附加到tcp_send_reset(),通过kprobe/fentry附加到tcp_v4_send_reset(),只需要通过测试tcp_v4_send_reset()延迟即可比较二者性能差异

相关仓库: - 测试负载代码仓库: https://github.com/1037827920/test-for-rstreason - ebpf程序代码仓库: https://github.com/1037827920/libbpf-template

工具介绍: - perf-prof,这是一个基于perf的工具,可以通过perf probe来附加探针后进行统计内核函数运行时间。直接下载源码编译即可。 - perf,用于系统性能调优,瓶颈定位和应用程序行为分析。利用硬件性能计数器(PMU)、软件事件、tracpoints、kprobes和uprobes等机制,提供对内核和用户空间的深入观察能力

无探针情况

概述: 首先我们要先测试在没有任何ebpf程序附加的情况下,内核函数的运行时间,以此来作为baseline。

测试步骤: 1. 增加probe点:

1
2
perf probe --add tcp_v4_send_reset
perf probe --add "tcp_v4_send_reset%return"
2. 执行perf-prof工具:
1
perf-prof multi-trace -e "probe:tcp_v4_send_reset" -e "probe:tcp_v4_send_reset__return"
3. 执行测试负载:
1
2
# 执行仓库test-for-rstreason下的脚本
bash test-skb-performance.sh

测试结果:

针对tracepoint类型

概述: 在将ebpf程序附加到tracepoint上,测试内核函数的延迟

测试步骤: 1. 将ebpf程序附加到tcp_send_reset()tracepoint:

1
2
# 执行仓库libbpf-template examples/tracepoint/tcp_send_reset下的程序
./main
2. 执行perf-prof工具:
1
perf-prof multi-trace -e "probe:tcp_v4_send_reset" -e "probe:tcp_v4_send_reset__return"
3. 执行测试负载:
1
2
# 执行仓库test-for-rstreason下的脚本
bash test-skb-performance.sh

测试结果:

针对kprobe类型

概述: 在将ebpf程序附加到tracepoint上,测试内核函数的延迟。因为perf probe机制其实就是通过给函数的入口和出口以kprobe的方式附加ebpf程序进行延迟计算,而内核是无法确定你注册的两个ebpf程序的执行顺序,所以在针对附加了kprobe类型ebpf程序的内核函数延迟计算,我想到的方法就是直接在要附加的ebpf程序的入口和出口都进行时间戳的记录然后计算delta值

测试步骤: 1. 将ebpf程序附加到tcp_v4_send_reset()kprobe:

1
2
# 执行仓库libbpf-template examples/kprobe/tcp_v4_send_reset下的程序
./main
2. 执行perf-prof工具:
1
perf-prof multi-trace -e "probe:tcp_v4_send_reset" -e "probe:tcp_v4_send_reset__return"
3. 执行delta值计算脚本:
1
2
# 执行仓库test-for-rstreason下的脚本
bash collect-delta.sh
4. 执行测试负载:
1
2
# 执行仓库test-for-rstreason下的脚本
bash test-skb-performance.sh

测试结果:

结果

类型 无probe tracepoint kprobe
时间(ns) 8.299 13.894 23.430

可以看到kprobe的性能是要比tracepoint的差的

fentry和kprobe谁先执行?

概述: 在一开始的时候,作者想直接通过fentry的方式来计算带有kprobe类型ebpf程序的内核函数延迟,即通过funclatency(这是bcc中的一个工具)。但是想要这样测试,必须先验证一下二者的执行顺序,作者一开始没有做实验被坑惨了

方法: 通过bpftrace快速编写ebpf程序进行测试

测试步骤:

  1. 附加一个kprobe类型的ebpf程序:
1
2
3
4
5
6
7
8
9
bpftrace -e '
kprobe:tcp_v4_send_reset {
debugf("kprobe Enter tcp_v4_send_reset");
}

kretprobe:tcp_v4_send_reset {
debugf("kretprobe Exit tcp_v4_send_reset");
}
'
  1. 附加一个fentry类型的ebpf程序:
1
2
3
4
5
6
7
8
9
bpftrace -e '
kfunc:tcp_v4_send_reset {
debugf("fentry Enter tcp_v4_send_reset");
}

kretfunc:tcp_v4_send_reset {
debugf("fexit Exit tcp_v4_send_reset");
}
'
  1. 执行测试程序:
1
2
# 执行仓库test-for-rstreason下的脚本
bash test-skb-reset-reason.sh
  1. 观察:
1
cat /sys/kernel/debug/tracing/trace_pipe

结果:

可以看到是先执行kprobe类型的ebpf程序的,即使把kprobe和fentry的附加顺序换一下还是一样的结果


如何追踪追踪程序
http://example.com/2025/05/19/如何追踪追踪程序/
作者
凌云行者
发布于
2025年5月19日
许可协议