Callgrind概述
和gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。和gprof不同,它不需要在编译源代码时附加特殊选项,但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据,建立函数调用关系图,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
使用callgrind工具生成性能分析数据
命令格式如下:
valgrind --tool=callgrind ./test
其中 ./test就是我们要分析的程序。执行完毕后,就会在当前目录下生成一个文件。文件名为“callgrind.out.进程号”。如,callgrind.out.31113。注意,对于daemon进程的调试,不要通过kill -9方式停止,要用Ctrl + C。
如果你调试的程序是多线程,你也可以在命令行中加一个参数 -separate-threads=yes。这样就会为每个线程单独生成一个性能分析文件。如下:
valgrind --tool=callgrind --separate-threads=yes ./test
生成的文件除了callgrind.out.31113外,还会多出一些子线程的文件。文件名如下:
callgrind.out.31113-01 callgrind.out.31113-02 callgrind.out.31113-03
把callgrind生成的性能数据转换成dot格式数据
可以使用gprof2dot.py脚本,把callgrind生成的性能分析数据转换成dot格式的数据。方便使用dot把分析数据图形化。
脚本可以 点此下载 。脚本使用方式如下:
python gprof2dot.py -f callgrind -n10 -s callgrind.out.31113 > valgrind.dot
使用dot把数据生成图片
命令格式如下:
dot -Tpng valgrind.dot -o valgrind.png
示例:
测试代码:
#include <stdio.h>
#include <stdlib.h>
void f1() {
int i;
int *p;
for (i = 0; i < 10; i++) {
p = malloc(sizeof(int));
*p = 10;
free(p);
}
}
void f2() {
int i;
int *p;
for (i = 0; i < 20; i++) {
p = malloc(sizeof(int));
*p = 10;
free(p);
}
}
void f3() {
int i;
int *p;
for (i = 0; i < 30; i++) {
p = malloc(sizeof(int));
*p = 10;
free(p);
}
}
int main() {
int i;
for (i = 0; i < 1000; i++) {
f1();
f2();
f3();
}
return 0;
}
编译
gcc -g test_main.c -o test_main
性能分析命令
valgrind --tool=callgrind ./test_main --dump-instr=yes --trace-jump=yes
[root@localhost louis_li]# ll
总用量 44
-rw------- 1 root root 26499 Jul 4 21:01 callgrind.out.10798
-rwxr-xr-x 1 root root 9289 Jul 4 20:48 test_main
-rw-r--r-- 1 root root 516 Jul 4 20:48 test_main.c
用kcachegrind 打开callgrind.out.10798 ,即显示下面图 (在 ubuntu上也可以直接 aptitude install kcachegrind安装)
LINUX: http://kcachegrind.sourceforge.net/html/Home.html
windows: https://sourceforge.net/projects/precompiledbin/files/?source=navbar
查看结果
执行完上述命令后,在当前目录下生成 callgrind.out.<pid>文件,linux使用可视化kcachegrind查看
kcachegrind callgrind.out.10798