最近在网上看到了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

欢迎关注我的公众号“灯珑”,让我们一起了解更多的事物~

你也可能喜欢

发表评论