使用Systemtap生成Flame Graph(火焰图)

本文介绍如何在CentOS 6.4环境下使用SystemTap生成FlameGraph火焰图,包括检查内核支持、安装所需软件包、编写SystemTap脚本、执行脚本并对nginx进行压测、生成火焰图的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/justlinux2010/article/details/11171291
之所以再写一篇博客,主要是原文的内容显示的有问题,直接贴文章中的脚本有问题,另外文章中也没有说明可能遇到的一些问题。
以下的安装步骤是在CentOS 6.4下进行的,内核版本是2.6.32-358.el6.x86_64,选择的应用软件是nginx-1.4.2。
1、检查内核是否提供utrace/uprobes用户态支持
打开/boot/config-2.6.32-358.el6.x86_64文件(内核版本不同,文件名不同),检查CONFIG_UTRACE宏是否设置。如果没有,很遗憾,要么自己打上补丁重新编译内核,或者选择其他的内核版本。
2、安装所需要的包
Systemtap的安装需要systemtap和systemtap-runtime rpm包。由于SystemTap是将脚本编译成内核模块然后插入到系统中,需要内核源码树,因此要安装kernel-devel、kernel-debuginfo、kernel-debuginfo-common包。debuginfo包在 debuginfo.centos.org下载。
3、编写SystemTap脚本
global bt
global quit = 0

probe timer.profile {
if (pid() == target()) {
if (!quit) {
bt[backtrace(), ubacktrace()] <<<1
else {
foreach ([sys, usr]  in bt- limit1000) {
print_stack(sys)
print_ustack(usr)
printf("\t%d\n", @count(bt[sys, usr]))
}
exit()
}
}
}

probe timer.s(20) {
quit = 1
}
脚本的主要功能是在每个时钟tick都进行一次采样,采集的指定进程的内核栈信息和用户态栈信息,20s后开始退出,并输出结果。将上面的脚本保存在fire.stp。
4、对nginx进行压测并执行脚本
使用ab、polygraph等工具对nginx进行压测,然后执行脚本,命令如下:
stap --ldd -d /usr/local/nginx/sbin/nginx \
--all-modules-D MAXMAPENTRIES=10240 \
-D MAXACTION=20000 \
-D MAXTRACE=100 \
-D MAXSTRINGLEN=4096 \
-D MAXBACKTRACE=100-x 1750 fire.stp>a.out
-d选项指定需要的符号信息来源,这里指定的就是可执行文件的路径,注意在编译nginx时要加上-g选项。-D选项是用来设置一些宏,这里用到的宏都是一些关于资源限制的,根据自己的环境修改,具体的含义参见man stap。-x用来指定针对的进程,从nginx的work进程中选择一个即可。fire.stp是脚本文件,a.out用来存储输出,用于在后面生成火焰图。
前面已经检查了运行stap脚本所需要的环境,但是在执行这步的话还是可能会报下面的警告:
WARNING: Missing unwind data  for module, rerun with 'stap -d stap_554dc449843d32431205d7d8e384a4e_22086'
WARNING: _stp_read_address failed to access memory location
ERROR: Skipped too many probes, check MAXSKIPPEDor try again with stap-t for more details.
WARNING: Number of errors:0, skipped probes:105
WARNING: /usr/bin/staprun exited with status:1
Pass 5: run failed. Try again with another'--vp 00001' option.
在网上看到很多人遇到,不过没有关系,在Google Groups看到章亦春说这个没有影响,只要能正常生成火焰图就行。我的火焰图就是在这种警告下生成的,而且有时还会报utrace/uprobes不支持等警告,忽略这些警告即可。
5、生成火焰图
生成火焰图需要两个perl脚本,脚本在FlameGraph,执行过程如下所示:
[root@FWD_YF_009_111 ~]# perl stackcollapse-stap.pl a.out > a.out2
[root@FWD_YF_009_111 ~]# perl flamegraph.pl a.out2 > a.svg
在window下用浏览器打开a.svg文件,就能看到类似下面的图:

火焰Flame Graph)是一种用于**性能分析**的可视化工具,广泛用于分析 CPU 使用、调用栈、热点函数、锁竞争、I/O 等问题。它由 Brendan Gregg 发明,常用于 Linux 性能分析工具如 `perf`、`ebpf`、`DTrace`、`SystemTap` 等输出的数据。 --- ## ✅ 一、火焰的结构和含义 火焰的结构是一个**调用栈堆叠**,每个矩形代表一个函数调用帧: - **X 轴**:代表调用栈的样本数(即时间占比),宽度越宽,表示该函数占用 CPU 时间越长。 - **Y 轴**:代表调用栈深度,越往上是更接近 CPU 的函数(即叶子函数),越往下是调用链的入口函数。 - **颜色**:通常没有语义含义,只是为了区分不同的函数。 ### 🔍 示例结构: ``` main └── process_request ├── read_data │ └── read_from_disk └── compute_result └── slow_function ``` 在火焰中,`slow_function` 可能会占很大一块,说明它是性能瓶颈。 --- ## ✅ 二、如何生成火焰 ### 1. 使用 `perf` 工具采集数据 ```bash # 采集整个系统的 CPU 使用情况(持续 30 秒) sudo perf record -F 99 -a -g -- sleep 30 ``` - `-F 99`:每秒采样 99 次 - `-a`:采集所有 CPU - `-g`:采集调用栈 - `sleep 30`:采集 30 秒 ### 2. 生成火焰数据 ```bash # 导出 perf 数据为调用栈折叠格式 sudo perf script | ./stackcollapse-perf.pl > out.perf-folded # 生成火焰 SVG 文件 ./flamegraph.pl out.perf-folded > flamegraph.svg ``` > 你需要先安装 Flame Graph 工具包: ```bash git clone https://github.com/brendangregg/FlameGraph ``` --- ## ✅ 三、如何看火焰 ### 🔍 关键观察点: 1. **宽条函数**:说明该函数占用 CPU 时间较多,是潜在的性能瓶颈。 2. **深调用栈**:查看函数调用路径,找出热点路径。 3. **重复模式**:如某个库函数频繁出现,可能是热点函数。 4. **系统调用或锁竞争**:如 `sys_read`、`pthread_mutex_lock` 占比较高,说明 I/O 或并发问题。 ### 📌 示例分析: 如果你看到: ``` main └── handle_http_request └── slow_database_query └── mysql_real_query ``` 说明 `slow_database_query` 是性能瓶颈,可能需要优化数据库查询。 --- ## ✅ 四、火焰的常见类型 | 类型 | 用途 | |------|------| | CPU 火焰 | 分析 CPU 使用热点 | | 内存火焰 | 分析内存分配热点 | | 锁竞争火焰 | 分析线程锁等待 | | I/O 火焰 | 分析磁盘或网络 I/O 等待 | | Off-CPU 火焰 | 分析线程被调度出 CPU 的原因(如睡眠、等待 I/O) | --- ## ✅ 五、火焰使用技巧 ### 1. **过滤特定进程或线程** ```bash # 仅采集 PID=1234 的进程 sudo perf record -p 1234 -g -F 99 sleep 30 ``` ### 2. **按用户态/内核态分开查看** ```bash # 用户态 sudo perf record -u -g -F 99 -p 1234 sleep 30 # 内核态 sudo perf record -k -g -F 99 -p 1234 sleep 30 ``` ### 3. **交互式火焰** 使用 `FlameScope`、`SpeedScope` 等工具可以实现交互式火焰分析,支持缩放、搜索、调用栈展开等。 --- ## ✅ 六、实战示例 ### 场景:发现 CPU 使用率高 - 生成火焰后发现: ``` main └── render_page └── generate_html └── expensive_template_render ``` - 分析:`expensive_template_render` 函数占用了大量 CPU,需要优化模板引擎或缓存结果。 --- ## ✅ 七、相关问题推荐
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值