最近在网上看到了tikv开源的pprof-rs库,提供了对rust程序进行profiling的功能。能够绘制火焰图,或者是pprof的callgraph。能够比较方便的对比同一个rust程序的两个版本之间,性能差异点在哪。(比如升级了rust,然后性能变慢了)
仓库地址:https://github.com/tikv/pprof-rs
本文基于pprof-rs 0.14.0 (0fa575e0caee54732db734eedb1d16f850d01468)
准备工作
引入这个库
pprof-rs是嵌入到要分析的应用程序里面的,因此,在数据采集这块,只要类似下面这样干就行(要启用pprof feature):
match guard.report().build() {
Ok(report) => {
let mut file = File::create("profile.pb").unwrap();
let profile = report.pprof().unwrap();
let mut content = Vec::new();
profile.encode(&mut content).unwrap();
file.write_all(&content).unwrap();
println!("report: {}", &report);
}
Err(_) => {}
};
安装go、pprof
pprof-rs只是用于采集数据,我们分析结果需要使用google的pprof库。因此需要安装go。
安装完go之后,输入以下命令安装pprof:
go install github.com/google/pprof@latest
测试
为了方便演示,把上面的pprof-rs仓库克隆到本地。然后我们对它的examples文件夹下的profile_proto_with_prost.rs文件进行测试。
查看程序的调用图
cargo run --example profile_proto_with_prost --features="protobuf prost-codec"
这样会在当前目录下生成一个profile.pb
文件。我们将其重命名为profile001.pb
,接着运行以下命令:
~/go/bin/pprof -svg profile001.pb
然后会生成一个profile001.svg
图片,浏览器打开之后可以看到调用图。
如何阅读调用图?
这里引用pprof的说明文档:
https://github.com/google/pprof/blob/main/doc/README.md#interpreting-the-callgraph
- 节点颜色:
- 累积值大的用红色表示。
- 累积值小的用绿色表示;负值在性能分析比较时最可能出现,具体详情请参见本节。
- 接近零的累积值用灰色表示。
- 节点字体大小:
- 字体较大的表示绝对平坦值较大。
- 字体较小的表示绝对平坦值较小。
- 边权重:
- 边较粗表示该路径使用了更多资源。
- 边较细表示该路径使用了较少资源。
- 边颜色:
- 正值较大的用红色表示。
- 负值较大的用绿色表示。
- 接近零的值用灰色表示。
- 边形状:
- 虚线边:两个连接位置之间的某些位置被移除了。
- 实线边:一个位置直接调用另一个位置。
- “(内联)”边标记:该调用已被内联到调用者中。
生成对比图
接下来,我们修改profile_proto_with_prost.rs
,在is_prime_number1()
函数里面加一个循环,以消耗cpu时间:
然后再次运行:
cargo run --example profile_proto_with_prost --features="protobuf prost-codec"
接着,把生成的profile.pb重命名为profile002.pb
然后,使用以下命令,生成对比图:
~/go/bin/pprof -svg -base profile001.pb -normalize profile002.pb
正则化后的对比图如下,可以看到is_prime_number1()
函数耗时上升了0.96s,根据调用图,再去追查源代码,就能分析出,是我们上面添加的那个循环搞的鬼。
转载请注明来源: https://longjin666.cn/?p=1932
欢迎关注我的公众号“灯珑”,让我们一起了解更多的事物~