Gprof 实践
Profiling 是一种可以有效度量软件程序性能的方法,常用的技术包括 event-based, statistical, instrumented, and simulation methods 等。Linux 上常用的 Profiling 工具有 Gprof, perf, Valgrind, OProfile, Google 的 gperftools 等,这其中我用过 Gprof 和 Valgrind,但我后面会更关注 perf,本文简单介绍 Gprof 的使用方法。
Gprof 的使用大致可以分为三步,我们以一个 JPEG 图片压缩库 Brunsli 为例来看下 Gprof 的使用方法。
实验在一个 v.memory = 1024; v.cpus = 2
的虚拟机上进行:
vagrant@ubuntu-xenial:~$ git clone --depth=1 https://github.com/google/brunsli.git
vagrant@ubuntu-xenial:~$ cd brunsli
vagrant@ubuntu-xenial:~/brunsli$ git submodule update --init --recursive
1. 添加编译/链接参数 -pg
编译添加 -pg
是为了在对象文件中生成额外的 profiling 信息;而链接添加 -pg
是为了链接 gcrt0.o 而非 crt0.o,从而能在 main 函数之前调用 profiling 相关的初始化函数。我们在修改 brunsli 的 Makefile:
CFLAGS += -O2 -std=c++11 -ffunction-sections -pg
LDFLAGS += -Wl,-gc-sections -pg
编译:
vagrant@ubuntu-xenial:~/brunsli$ make
2. 运行程序
由于第 1 步已经将 profiling 需要的信息写在了可执行文件中,因此该步骤跟正常执行一个程序完全一样:
vagrant@ubuntu-xenial:~/brunsli$ bin/cbrunsli docs/WIEGO_ACCRA_8008_FULLY_RELEASED-scaled.p.jpg
执行完之后会生成一个 gmon.out 的文件,这里边包含了后面用 gprof
进行查看分析的所有 profiling 信息。
3. 使用 gprof 进行分析
gprof 展示的结果分两部分: The Flat Profile 和 The Call Graph,具体说明见手册。
vagrant@ubuntu-xenial:~/brunsli$ gprof bin/cbrunsli
Bonus
使用 gprof2dot 可以将 gprof 的 Call Graph 生成直观的图片:
vagrant@ubuntu-xenial:~/brunsli$ pip install gprof2dot
vagrant@ubuntu-xenial:~/brunsli$ sudo apt-get install graphviz
vagrant@ubuntu-xenial:~/brunsli$ gprof bin/cbrunsli | gprof2dot | dot -Tpng -o output.png
Pros&Cons
Pros:
- GCC 原生支持,不需要额外安装其它库,简单易用
- call graph 能清晰展现出程序的调用关系
Cons:
- 修改代码需要重新编译,对于大型项目来说意味着很耗时间
- 采样率 100ps,略低
- 由于往 gmon.out 写 profiling 数据是通过 atexit() 调用了 mcleanup,因此在程序异常退出的情况下得不到 profiling 数据
注: 后面笔者会重点关注 perf