Linux 性能调优系列(十三): 从 SystemTap 到 eBPF,Linux 性能追踪进入新时代
1 | 作者:李晓辉 |
上一篇我们刚学完 SystemTap。SystemTap 有一个很厉害的能力:
不改应用代码,也不用重新编译内核,就可以给 Linux 内核和系统行为“装探针”。
但是学到这里,大家可能也会有一个问题:
现在 Linux 性能分析,为什么越来越多人开始讲 eBPF?
其实原因很简单。SystemTap 的工作方式,是把脚本转换成 C 代码,再编译成内核模块,最后加载到内核里运行。
而 eBPF 采用的是另一套思路:
让一段经过内核 verifier 检查的程序进入内核,在受约束的执行环境中完成追踪和数据采集。
所以相比直接加载自定义内核模块,eBPF 在安全边界、动态追踪以及生产环境使用方面具有明显优势。而且更重要的是:
你根本不需要一上来就学 eBPF C 代码。
因为已经有 BCC、bpftrace 这些工具帮我们把复杂的东西封装起来。这篇文章,我们就先不钻 eBPF 源码。先站在运维工程师的角度,看看:
eBPF 到底能帮我们解决什么问题?
eBPF概述
eBPF 是什么?
第一次接触 eBPF,很多人看到各种文章之后,第一反应可能是:
“又来了一个特别复杂的 Linux 内核技术……”
其实不用想得那么复杂。如果把 Linux 内核理解成一座正在高速运行的工厂,那么以前我们想知道工厂里面发生了什么,通常只能通过现有的监控接口去观察。
例如:
1 | top |
这些工具已经非常强大。但是,当你想问一些更加具体的问题时,比如:
- 到底是谁频繁创建进程?
- 哪个程序一直在打开某个文件?
- 某个磁盘 IO 到底慢在哪里?
- 某个进程为什么一直等待 CPU?
- DNS 解析到底花了多少时间?
- 某个内核函数到底被调用了多少次?
传统工具有时候就不够用了。这时候,eBPF 就派上用场了。
eBPF 到底干什么?
eBPF 可以让我们把一段程序加载到 Linux 内核中,并把它挂到特定的事件或 hook 上。当事件发生的时候,eBPF 程序就会被执行。例如:
1 | 进程创建 |
所以它非常适合做:
- 性能分析;
- 内核追踪;
- 网络分析;
- 文件系统分析;
- IO 分析;
- 进程行为分析;
- 容器和 cgroup 相关观测。
老李也把 bpftrace 和 BCC 定位为用于分析 Linux 系统性能、收集其他接口难以获取的信息的重要工具。
eBPF 为什么比传统内核模块更安全?
这里正好可以和上一篇的 SystemTap 对比一下。
SystemTap 最终会把脚本转换成 C 代码,然后编译成内核模块。
而 eBPF 程序在加载到内核之前,会经过 BPF verifier 等机制检查。
比如:
- 程序执行路径是否满足约束;
- 内存访问是否安全;
- 是否存在越界访问;
- 使用的 helper 是否允许;
- 对 map 等对象的访问是否符合规则。
如果程序无法通过 verifier,通常就不会被加载。
所以可以简单理解成:
SystemTap 更像是生成一个内核模块再加载进去;eBPF 更像是把一段受约束、经过检查的小程序交给内核运行。
当然,这里也不能把 eBPF 理解成“绝对不会出问题”。eBPF、内核以及相关工具本身仍然可能存在 bug。更准确的说法是:
普通 eBPF 程序受到 verifier 和运行环境的约束,相比直接加载任意内核模块,安全边界更强,因此更适合现代 Linux 的动态追踪和生产环境观测。
eBPF 可以挂在哪里?
既然 eBPF 可以观察内核事件,那么问题来了:
到底观察什么?
这就涉及 eBPF 常见的探测点。比较常见的有:
| 探测类型 | 主要用途 |
|---|---|
| kprobe | 动态探测内核函数 |
| kretprobe | 动态探测内核函数返回 |
| tracepoint | 使用内核预定义的静态追踪点 |
| perf event | 性能事件采样 |
| uprobe | 探测用户态函数 |
| uretprobe | 探测用户态函数返回 |
| cgroup | 针对 cgroup / 容器相关行为进行观测 |
| socket | 网络相关事件 |
这里大家不用急着把这些全部记住。现在只需要建立一个概念:
eBPF 本身不是一个单独的“监控命令”,而是一套可以挂到各种内核、用户态事件上的可编程机制。
比如:
flowchart LR
A[eBPF程序] --> B[探测点]
B --> C[kprobe]
B --> D[tracepoint]
B --> E[uprobe]
B --> F[perf event]
B --> G[cgroup]
B --> H[socket]
C --> I[采集事件]
D --> I
E --> I
F --> I
G --> I
H --> IeBPF 和 SystemTap 到底有什么区别?
上一篇我们已经学过 SystemTap,所以这里把两个放在一起看最容易理解。
| 对比项 | SystemTap | eBPF |
|---|---|---|
| 核心方式 | 脚本转换并编译成内核模块 | 加载 eBPF 程序到内核 |
| 安全机制 | SystemTap translator 提供约束,但内核模块能力较强 | verifier 等机制对程序进行检查 |
| 追踪能力 | 很强 | 很强 |
| 动态追踪 | 支持 | 支持 |
| 用户态追踪 | 支持 | 支持 |
| 生产环境 | 需要谨慎 | 现代 Linux 中应用越来越广泛 |
| 学习方式 | SystemTap 脚本 | BCC / bpftrace / libbpf 等 |
| 常见用途 | 传统动态追踪、复杂系统分析 | 现代性能分析、可观测性、网络和内核追踪 |
这里最容易产生一个误区:
是不是 eBPF 出现以后,SystemTap 就没用了?
也不能这么理解。SystemTap 仍然可以用于一些传统 Linux 环境和特定的复杂追踪场景。只是对于现代 Linux 系统,尤其是生产环境性能分析、网络观测、容器观测等场景,eBPF 已经成为非常重要的一条技术路线。所以更准确的理解是:
不是 SystemTap “淘汰”了,而是 eBPF 正逐渐成为现代 Linux 动态追踪的重要基础设施。
BCC 和 bpftrace 又是什么?
到这里,新的问题来了。我们刚才说的是 eBPF。那为什么又冒出来:
1 | BCC |
其实很好理解。
eBPF 是底层技术,BCC 和 bpftrace 是帮助我们使用 eBPF 的工具。
可以把它们理解成:
1 | eBPF |
BCC:直接拿现成工具来用
BCC 全称:
BPF Compiler Collection
它提供了一套基于 eBPF 的工具和开发框架。对于运维人员来说,最吸引人的地方其实不是它的名字,而是:
已经有人把很多常见的性能排查场景做成工具了。
例如:
1 | execsnoop |
所以你遇到问题的时候,不需要自己从零开始写 eBPF。
比如:
“我想看看服务器现在谁在不断创建进程。”
不用写 eBPF。
直接:
1 | /usr/share/bcc/tools/execsnoop |
就可以开始观察。
安装 bcc-tools 后,这些工具位于:
1 | /usr/share/bcc/tools/ |
建议直接查看这个目录以及其中的 doc 子目录。
bpftrace:自己写一点简单的追踪逻辑
如果说 BCC 是:
工具箱
那么 bpftrace 更像:
一门专门用来快速写追踪脚本的小语言。
它的语法比较简洁,特别适合:
- 快速验证一个想法;
- 临时排查一个问题;
- 写一条 one-liner;
- 写一个简单的自定义追踪脚本。
例如:
1 | bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args.filename)); }' |
这条命令可以实时观察进程打开文件的行为。
所以:
BCC 更像“拿工具直接干活”,bpftrace 更像“自己写几行脚本解决特殊问题”。
安装 BCC 和 bpftrace
安装 BCC:
1 | [root@localhost ~]# dnf install bcc-tools -y |
安装 bpftrace:
1 | [root@localhost ~]# dnf install bpftrace -y |
也可以一次安装:
1 | [root@localhost ~]# dnf install bcc-tools bpftrace -y |
安装完成以后,可以分别看看:
1 | [root@localhost ~]# ls /usr/share/bcc/tools/ |
以及:
1 | [root@localhost ~]# ls /usr/share/bpftrace/tools/ |
BCC 工具位于:
1 | /usr/share/bcc/tools/ |
而bpftrace 示例脚本位于:
1 | /usr/share/bpftrace/tools/ |
execsnoop:看看系统里谁在创建进程
我们先从一个非常直观的工具开始。
1 | [root@localhost ~]# /usr/share/bcc/tools/execsnoop |
execsnoop 用来观察系统中的新进程执行事件。
它特别适合排查:
- 谁在不断启动进程?
- 某个短命进程到底执行了什么?
- 定时任务到底在执行什么?
- 某个脚本是不是被反复执行?
- 系统里有没有出现异常命令?
例如运行:
1 | /usr/share/bcc/tools/execsnoop |
然后在另一个终端执行:
1 | ls |
你可能看到类似:
1 | PCOMM PID PPID RET ARGS |
几个重要字段:
| 字段 | 含义 |
|---|---|
| PCOMM | 父进程命令名 |
| PID | 进程 ID |
| PPID | 父进程 ID |
| RET | exec() 系统调用返回值 |
| ARGS | 执行程序及参数 |
这里大家注意一个细节:
execsnoop 更准确地说是在观察程序执行/exec 事件,而不是简单等同于“进程创建”。因为 Linux 创建进程和执行新程序是两个不同层面的动作。
这个区别在学习 fork()、clone()、execve() 的时候会非常重要。
opensnoop:程序到底打开了什么文件?
再来看一个特别实用的工具:
1 | [root@localhost ~]# /usr/share/bcc/tools/opensnoop |
它可以观察文件打开事件。
可以重点关注:
1 | ERR = 0 |
表示打开成功。
如果出现非 0 值,就需要进一步关注对应错误。
比如:
1 | ERR = 2 |
通常对应:
1 | ENOENT |
也就是:
文件或目录不存在。
这个时候排查配置文件问题就特别直观。比如应用启动时报:
1 | config.yml not found |
你可能会想:
“我明明把配置文件放在那里了啊?”
不要猜。
直接:
1 | /usr/share/bcc/tools/opensnoop |
看看程序实际尝试打开的到底是哪一个路径。
biolatency:磁盘 IO 到底有多慢?
前面我们学习过 iostat。iostat 可以告诉我们:
磁盘现在忙不忙。
但是有时候我们真正想知道的是:每一次 IO 的延迟到底是什么分布?
这时候就可以使用:
1 | [root@localhost ~]# /usr/share/bcc/tools/biolatency |
这里最重要的是理解:
1 | 延迟区间 → 有多少 IO 落在这里 |
而不是死记某个数字。比如你发现:
1 | 大多数 IO:10~50us |
下一步应该问:
这是不是正常?
答案不能脱离环境直接下结论。
因为:
- 本地 NVMe;
- SATA SSD;
- 云盘;
- SAN;
- 虚拟机磁盘;
- 容器存储;
它们的正常延迟范围本来就可能不同。所以 biolatency 最重要的价值,是帮你看到:
IO 延迟的分布和长尾。
biosnoop:不要只看“磁盘慢”,直接看到每一条 IO
biolatency 告诉我们:
延迟分布怎么样。
那如果我还想知道:
到底是谁在产生这些 IO?
可以进一步使用:
1 | [root@localhost ~]# /usr/share/bcc/tools/biosnoop |
它会把块设备 IO 请求逐条显示出来。
重点看:
| 字段 | 含义 |
|---|---|
| COMM | 进程名 |
| PID | 进程 ID |
| DISK | 磁盘设备 |
| T | IO 类型 |
| SECTOR | 起始扇区 |
| BYTES | IO 大小 |
| LAT(ms) | IO 延迟 |
比如:
1 | mysqld |
不断出现,而且:
1 | LAT(ms) |
明显比较高。那我们就有了一个非常具体的排查方向。
这比简单看一句:
1 | 磁盘利用率 100% |
有用得多。
xfsslower:XFS 到底哪里慢?
如果服务器使用 XFS 文件系统,还有一个非常实用的工具:
1 | [root@localhost ~]# /usr/share/bcc/tools/xfsslower |
它可以观察 XFS 上比较慢的文件系统操作。
例如:
1 | /usr/share/bcc/tools/xfsslower 1 |
表示:
只显示耗时超过 1ms 的操作。
这里特别容易写错。
xfsslower 默认并不是 1ms。
1 | xfsslower 1 |
才是只看超过 1ms 的操作。
例如:
1 | TIME COMM PID T BYTES OFF_KB LAT(ms) FILENAME |
这里可以看到:
- 谁执行了操作;
- 读还是写;
- 操作了多少数据;
- 延迟是多少;
- 对应文件是什么。
所以当应用出现文件访问延迟的时候,可以进一步判断:
1 | 应用 |
到底是哪一层慢。
cachestat:数据到底是在内存里,还是跑去磁盘了?
Linux 有一个非常重要的机制:
Page Cache(页缓存)
应用读取文件的时候,并不一定每次都需要直接访问磁盘。如果数据已经在页缓存里,读取就可能直接从内存完成。所以有时候应用读取数据变慢,我们就会产生一个问题:
“是不是缓存没命中了?”
这时候可以看看:
1 | [root@localhost ~]# /usr/share/bcc/tools/cachestat |
它可以帮助观察页缓存相关的命中、未命中等情况。
这里:
| 字段 | 含义 |
|---|---|
| HITS | 命中 |
| MISSES | 未命中 |
| DIRTIES | 脏页相关统计 |
| RATIO | 命中率 |
比如发现:
1 | MISSES |
突然明显增加,同时:
1 | RATIO |
明显下降。这时候就值得进一步结合:
1 | 内存使用 |
一起分析。但是这里也有一个非常重要的原则:
缓存命中率高,不一定代表业务一定快;缓存命中率低,也不一定代表系统有问题。
比如:
- 顺序扫描;
- 大规模备份;
- 数据重建;
- 一次性读取大量冷数据;
本来就可能产生大量 cache miss。所以 cachestat 给我们的是线索,不是最终结论。
gethostlatency:DNS 到底是不是慢?
再来看一个非常容易被忽略的问题:
DNS。
有时候应用请求外部服务超时。我们第一反应通常是:
1 | 网络是不是有问题? |
然后:
1 | ping |
查了一圈,网络好像都没问题。那有没有可能:
DNS 解析本身就花了很长时间?
可以使用:
1 | [root@localhost ~]# /usr/share/bcc/tools/gethostlatency |
观察域名解析相关延迟。
重点关注:
1 | HOSTNAME |
比如:
1 | www.linuxcenter.cn |
一直出现:
1 | 100ms |
那就要开始怀疑 DNS 解析链路。这类问题特别适合用 eBPF,因为我们不再只是观察“网络通不通”,而是直接观察:
某个事件到底花了多少时间。
还有哪些 BCC 工具值得记住?
BCC 工具非常多,我们不可能全部学。这里记住几个经常会碰到的就行。
runqlat:CPU 到底是不是在排队?
1 | [root@localhost ~]# /usr/share/bcc/tools/runqlat |
它用于观察任务等待 CPU 运行队列的时间。
如果你发现:
1 | CPU 使用率很高 |
还不够。我们还想知道:
任务是不是因为 CPU 太忙,一直排队?
这时候 runqlat 就很有价值。
biotop:到底谁在吃磁盘 IO?
1 | [root@localhost ~]# /usr/share/bcc/tools/biotop |
如果你不想一上来就分析每一条 IO,可以先用 biotop 看:
哪个进程正在产生最多的 IO。
这样就可以先快速定位:
1 | 到底是谁在疯狂读写磁盘? |
tcpconnect / tcpaccept:谁在建立 TCP 连接?
主动连接:
1 | /usr/share/bcc/tools/tcpconnect |
被动接受连接:
1 | /usr/share/bcc/tools/tcpaccept |
这两个工具非常适合观察:
1 | 谁在主动建立连接? |
比如服务器突然出现大量短连接,你就可以进一步观察到底是哪一个进程在产生这些连接。
bpftrace:自己写第一个追踪脚本
前面说了:
BCC 更像现成工具箱。
那么,如果现成工具没有满足你的需求怎么办?这时候就轮到:
1 | bpftrace |
登场了。
第一个 bpftrace 脚本
比如我们想统计:
每个进程调用
openat系统调用多少次。
可以写:
1 |
|
保存成:
1 | xiaohui.sh |
然后执行:
1 | [root@localhost ~]# bpftrace xiaohui.sh |
按:
1 | Ctrl+C |
退出以后,就可以看到按进程名统计出来的结果。
看懂 bpftrace 脚本
刚才这个脚本虽然只有几行,但里面其实已经包含了 bpftrace 最核心的几个概念。
1 | tracepoint:syscalls:sys_enter_openat |
先看第一行:
1 | tracepoint:syscalls:sys_enter_openat |
意思是:
把探针挂到
openat系统调用进入时对应的 tracepoint 上。
为什么这里使用 tracepoint?因为 Linux 内核已经预先定义好了这个追踪点。
bpftrace 官方教程也推荐通过 tracepoint 来观察 openat,并说明 tracepoint 是内核提供的静态追踪接口。
再看:
1 | @[comm] |
这里可以理解成一个 map。
comm 表示当前线程的命令名。
最后:
1 | count() |
就是:
每发生一次,就给对应的
comm计数。
所以整个脚本翻译成人话就是:
每当有人调用 openat,就找到这个进程的名字,然后给它加 1。
是不是一下就容易理解了?
bpftrace 常用变量
写脚本的时候,经常会碰到这些内置变量:
| 变量 | 含义 |
|---|---|
comm | 当前线程的命令名 |
pid | 当前进程 ID |
tid | 当前线程 ID |
uid | 当前用户 ID |
retval | 被追踪函数的返回值 |
args | 某些 probe 类型提供的事件参数 |
nsecs | 纳秒级时间戳 |
这些变量的具体可用范围和含义与 probe 类型有关。
例如:
1 | tracepoint |
通常可以通过:
1 | args.xxx |
访问 tracepoint 的参数。
而在:
1 | kprobe |
中,常见的是:
1 | arg0 |
等参数形式。
所以不要简单理解成:
“所有 bpftrace probe 都可以直接用 args。”
实际要看你使用的 probe 类型。
bpftrace 和 BCC,到底什么时候用哪个?
到了这里,可以简单做一个选择。
| 需求 | 推荐 |
|---|---|
| 已经有现成工具 | BCC |
| 想快速排查 IO | BCC |
| 想快速排查进程 | BCC |
| 想快速排查网络 | BCC |
| 想自己写一点追踪逻辑 | bpftrace |
| 想写一个临时 one-liner | bpftrace |
| 想深入开发 eBPF 工具 | libbpf / eBPF C 等 |
换句话说:
先找 BCC 有没有现成工具。
没有,再考虑 bpftrace。
如果 bpftrace 也无法满足,再往更底层的 eBPF 开发走。
对于运维人员来说,这条路线会轻松很多。
什么时候用哪个工具?
这一部分建议大家直接收藏。以后服务器出问题,可以直接翻回来找工具。
| 你想查什么 | 优先工具 |
|---|---|
| 谁在执行新程序? | execsnoop |
| 程序到底打开了哪些文件? | opensnoop |
| 哪些文件打开失败? | opensnoop |
| 磁盘 IO 延迟分布怎么样? | biolatency |
| 哪个进程在产生磁盘 IO? | biotop |
| 每一条 IO 到底发生了什么? | biosnoop |
| XFS 哪些操作比较慢? | xfsslower |
| Page Cache 表现怎么样? | cachestat |
| DNS 解析是不是慢? | gethostlatency |
| CPU 运行队列是不是拥堵? | runqlat |
| 谁在主动建立 TCP 连接? | tcpconnect |
| 谁在接受 TCP 连接? | tcpaccept |
| 现成工具不够用怎么办? | bpftrace |
一个真实的性能排查思路
现在我们把前面的工具串起来。
假设用户反馈:
“服务器最近很慢。”
这句话其实没有任何技术信息。不要一上来就:
1 | 重启! |
也不要直接:
1 | top |
看一眼 CPU 就开始猜。可以按照我们之前学习的性能分析思路逐层定位。
flowchart TD
A[服务器变慢] --> B[top / vmstat / iostat]
B --> C{问题方向}
C -->|CPU排队| D[runqlat]
C -->|磁盘IO| E[biolatency]
C -->|具体IO进程| F[biotop / biosnoop]
C -->|文件访问| G[opensnoop / xfsslower]
C -->|缓存问题| H[cachestat]
C -->|DNS问题| I[gethostlatency]
C -->|异常进程| J[execsnoop]
D --> K[进一步定位]
E --> K
F --> K
G --> K
H --> K
I --> K
J --> K比如:
第一步
先看:
1 | top |
发现:
1 | CPU 并没有特别高,但是 IO wait 比较明显 |
那就继续。
第二步
1 | /usr/share/bcc/tools/biolatency |
发现:
IO 延迟存在明显长尾。
那么下一步:
第三步
1 | /usr/share/bcc/tools/biotop |
看看:
到底哪个进程产生了最多 IO。
发现:
1 | mysqld |
比较突出。
那么再进一步:
第四步
1 | /usr/share/bcc/tools/biosnoop |
看看:
MySQL 到底产生了哪些 IO?哪些请求延迟最高?
这样一步一步下来,问题就从:
1 | 服务器很慢 |
变成:
1 | 服务器很慢 |
这才叫真正的性能排查。
生产环境使用 eBPF,需要注意什么?
eBPF 比直接加载内核模块更加受约束,但也不是:
“eBPF = 随便跑,完全没有成本。”
生产环境还是要注意。
优先使用现成工具
例如:
1 | execsnoop |
先解决问题,再考虑自己写复杂脚本。
不要长时间无脑追踪高频事件
比如某个 tracepoint 每秒触发几十万甚至几百万次。如果你把大量事件全部打印出来:
1 | 事件 → eBPF → 用户态 → terminal |
真正先被你搞死的,可能不是问题进程,而是你的终端。
所以:
能聚合统计,就不要逐条打印。
例如:
1 | @[comm] = count(); |
通常就比:
1 | 每一次事件都 printf |
更适合持续观察。
先统计,再定位
这是性能分析里非常重要的一条经验。不要一开始就:
“我把所有东西全部 trace 出来!”
正确的思路应该是:
1 | 先确定方向 |
例如:
1 | biolatency |
这比一上来就 biosnoop 一直刷屏更加合理。
容器和云环境中使用 eBPF
如果你是在:
- Docker
- Kubernetes
- 虚拟机
- 云服务器
里面使用 eBPF,还需要额外注意权限和内核环境。因为 eBPF 最终依赖的是:
实际运行环境的 Linux 内核和权限。
例如:
- 内核是否启用了相关 BPF 能力;
- 当前用户是否有权限加载对应程序;
- 容器是否被限制了相关 capability;
- 当前内核是否支持需要使用的 probe;
- BTF 等相关内核信息是否可用。
尤其是在容器里:
容器里的用户空间环境,并不等于宿主机的内核环境。
所以遇到:
1 | Operation not permitted |
或者:
1 | Cannot attach |
不要只盯着工具本身。
先看看:
1 | 内核 |
到底是哪一层出了问题。
常用帮助和文档
BCC 工具本身已经提供了不少文档。可以先看看:
1 | ls /usr/share/bcc/tools/doc/ |
例如:
1 | cat /usr/share/bcc/tools/doc/execsnoop_example.txt |
也可以使用:
1 | man execsnoop |
如果是 bpftrace,还可以直接查看:
1 | ls /usr/share/bpftrace/tools/ |
SystemTap、BCC、bpftrace,到底怎么选?
学到这里,我们已经有三套东西了:
1 | SystemTap |
再加上:
1 | perf |
是不是开始有点乱了?其实可以这样理解:
| 工具 | 主要关注点 | 典型用途 |
|---|---|---|
top | 整体资源 | CPU、内存快速观察 |
perf | CPU / 性能事件 | CPU 热点、性能采样 |
strace | 系统调用 | 进程到底调用了什么系统调用 |
ltrace | 用户态库函数 | 用户态函数调用 |
SystemTap | 动态追踪 | 复杂内核 / 系统行为追踪 |
BCC | eBPF 现成工具 | 快速性能排错 |
bpftrace | eBPF 脚本 | 快速自定义追踪 |
eBPF | 底层技术 | 内核、网络、可观测性等 |
所以以后遇到问题,可以先问自己:
我到底想知道什么?
例如:
CPU 跑得很高
1 | top |
某个进程系统调用很多
1 | strace |
怀疑大量文件打开
1 | opensnoop |
怀疑 IO 延迟
1 | biolatency |
想知道谁在产生 IO
1 | biotop |
想自己写一点 eBPF 追踪逻辑
1 | bpftrace |
这时候工具就不再是一堆需要死记硬背的命令,而变成了一套:
遇到什么问题,就拿什么工具。
系列小结:从 SystemTap 走向 eBPF
上一篇的 SystemTap,让我们第一次真正接触到了:
动态追踪 Linux 内核。
而这篇,我们进一步进入了现代 Linux 的 eBPF 世界。现在你应该已经知道:
1 | eBPF |
如果只记住一句话,可以记这个:
BCC 负责“拿现成工具直接干活”,bpftrace 负责“自己写几行脚本快速追踪”,而它们背后的底层技术,就是 eBPF。
至于 SystemTap 和 eBPF,也不要简单理解成:
“新技术一定把老技术淘汰了。”
更准确的理解应该是:
SystemTap 依然是一套强大的动态追踪工具,而 eBPF 正逐渐成为现代 Linux 内核追踪、性能分析、网络观测和可观测性的重要技术基础。
到这里,我们已经把 Linux 性能分析工具链又往前推进了一步:
1 | top |
