通常在程序遇到效能问题时,我们想找到到底哪些API在费时间并以此来分析效能问题,现存有很多工具可以得到这些数据,例如oprofile, perf, DTrace,但这些工具产生的分析数据都不是特别直观,本文主要是说明如何使用perf获取这些数据并生成可视化的图形帮助直观的进行分析.
Perf
Perf 是用来进行软件性能分析的工具,一般发行版本的linux可以直接安装perf,对于嵌入式系统需要自己编译
ubuntu系统中perf安装命令
sudo apt install linux-tools-common
#与具体的内核版本相关
sudo apt install linux-tools-5.4.0-192-generic linux-cloud-tools-5.4.0-192-generic
使用
抓取记录,perf record表示记录,-F 99表示每秒99次采样,-p 1336 是针对哪个进程进行抓取,-g表示记录调用栈,sleep 10则是持续10秒。
注意要使用root权限运行perf,否则会出现crash.
perf record -F 99 -p 1336 -g -- sleep 10
也可以使用下面命令抓取所有进程
perf record -F 99 -a -g -- sleep 10
抓取完后会产生一个perf.data文件,用下面命令将其转化为可被直接读懂的callstack信息文件 out.perf
perf script > out.perf
火焰图
其实一般的情况下使用下面命令也能够看到各个stack之间的调用关系和采样时间
perf report -n --stdio
生成的图长这个样:
但还是不易读和分析,于是就有了火焰图工具,该工具用pl脚本读取out.perf,画出各个函数的调用关系和占用时间。
下载
git clone https://github.com/brendangregg/FlameGraph.git
生成火焰图
用下面命令可以生成火焰图
./stackcollapse-perf.pl out.perf > out.folded
./flamegraph.pl out.folded > out.svg
生成后的结果实例如下(图片来源FlameGraph git),用chrome打开后可以点击查看分析那个函数最费时间。
这个图里面,横条长的就是花的时间长,就是需要进行优化的重点位置。
我遇到的是std::copy()用了很多的时间,经过了解,需要使用 -O3编译选项进行优化,优化后std::copy的时间就少了很多。
网上有讨论要不要用memcpy代替std::copy,因为std::copy与cpp 的特性结合的更好,所以建议使用std::copy。