valgrind安装+使用【附带callgrind + dot】

1.valgind 安装

1.1源码安装

获取源码:(也可点击链接下载)

wget http://www.valgrind.org/downloads/valgrind-3.16.0.tar.bz2

解压

tar -jxvf valgrind-3.16.0.tar.bz2 

安装

cd valgrind-3.16.0
./configure (./configure --prefix=/home/user1/valgrind 这种方式可以指定安装目录,但是可能需要配置环境才能使用)
make
make install

1.2指令安装(推荐)

sudo apt-get install valgrind

验证是否安装成功

valgrind --help

Ps:valgrind布置valgrind本身(线程安全,内存检查)还有callgrind(函数调用关系分析等)还有其他工具。只要安装valgrind也可以使用其他工具。

1.3基本介绍

包含如下工具:

  1. memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。
  2. callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。
  3. cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。
  4. helgrind:用于检查多线程程序的竞态条件。
  5. massif:堆栈分析器,指示程序中使用了多少堆内存等信息。

2.memcheck工具

例子:

valgrind -v --log-file=valgrind0928.log --tool=memcheck --leak-check=full --show-mismatched-frees=yes ./v2xAlgo

用法:
valgrind [options]prog-and-args [options]:常用选项,适用于所有Valgrind工具。
!!!使用valgrind的时候记得把编译条件的-pg关掉!!!!!!!。
常用选项释义:

  1. -tool=最常用的选项。运行valgrind中名为toolname的工具。默认memcheck。
  2. h –help显示帮助信息。
  3. -version显示valgrind内核的版本,每个工具都有各自的版本。
  4. q –quiet安静地运行,只打印错误信息。
  5. v –verbose更详细的信息,增加错误数统计。
  6. -trace-children=no|yes跟踪子线程? [no]
  7. -track-fds=no|yes跟踪打开的文件描述?[no]
  8. -time-stamp=no|yes增加时间戳到LOG信息? [no]
  9. -log-fd=输出LOG到描述符文件 [2=stderr]
  10. -log-file=将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID
  11. -log-file-exactly=输出LOG信息到 file
  12. -log-file-qualifier=取得环境变量的值来做为输出信息的文件名。 [none]
  13. -log-socket=ipaddr:port输出LOG到socket ,ipaddr:port

LOG信息输出

  1. -xml=yes将信息以xml格式输出,只有memcheck可用

  2. -num-callers= show callersin stack traces [12]

  3. -error-limit=no|yes如果太多错误,则停止显示新错误? [yes]

  4. -error-exitcode=如果发现错误则返回错误代码 [0=disable]

  5. -db-attach=no|yes当出现错误,valgrind会自动启动调试器gdb。[no]

  6. -db-command=启动调试器的命令行选项[gdb -nw %f %p]

适用于Memcheck工具的相关选项:

  1. -leak-check=no|summary|full要求对leak给出详细信息? [summary]

  2. -leak-resolution=low|med|high how much bt merging in leakcheck [low]

-show-reachable=no|yesshow reachable blocks in leak check? [no]

3.callgrind工具

例子:
valgrind --tool=callgrind --separate-threads=yes ./test
其中./test 就是我们要分析的程序。
-separate-threads=yes。这样就会为每个线程额外单独生成一个性能分析文件。
执行完毕后,就会在当前目录下生成一个进程观测文件和几个线程观测文件。
进程观测文件名为“callgrind.out.进程号”。线程观测文件名为“callgrind.out.进程号-01”,“callgrind.out.进程号-02”……。
例如:
callgrind.out.31113 callgrind.out.31113-01 callgrind.out.31113-02 callgrind.out.31113-03 …………

callgrind + dot绘图 用法:
单独查看子线程:

valgrind --tool=callgrind --separate-threads=yes ./test 

先用上述方法生成out文件。然后使用gprof2dot生成dot文件:

gprof2dot -f callgrind -s callgrind.out.7339-05 > callgrind05.dot

然后把dot文件生成图片:

dot -Tpng callgrind05.dot -o callgrind05.png 或者dot -Tsvg callgrind05.dot -o callgrind05.svg

其中-T为选择生图片的类型,有的时候png不好使会出现绘图失败的情况,建议换成svg

不单独查看子线程:

valgrind --tool=callgrind ./test 

先用上述方法生成out文件。然后使用gprof2dot生成dot文件:

gprof2dot -f callgrind -s callgrind.out.7339 > callgrind.dot

然后把dot文件生成图片:

dot -Tpng callgrind.dot -o callgrind.png 或者dot -Tsvg callgrind.dot -o callgrind.svg

4.callgrind辅助:kcachegrind 安装和使用

4.1定性分析

安装:

sudo apt-get install  kcachegrind

使用:

kcachegrind callgrind.out.7339-05

其中,callgrind.out.7339-05为通过callgrind生成的分析文件
定性分析

左侧为所有函数 及其相关信息
右侧选择call graph选项卡可以看左侧点选的函数的相关调用关系
目的:可以观测到更加精准的函数调用关系,通过gprof2dot 生成的图片是整个生命周期所调用到的函数。所以函数关系可能比较复杂。kcachegrind的callgraph可以帮忙过滤掉不必要的信息。

4.2 定量分析

定量分析
首先要介绍一下,kcache的相关按键。红框内的relative表示的是切换【该行函数的cpu周期数占比】和【该行函数的具体cpu周期数量】在定性分析时只需关注百分比即可。但是定量分析的时候具体的cpu周期数量就显得尤为重要。
那么如何阅读kcache的表格呢?
首先先要看懂表头的意思。

  • function和location分别是函数名和函数所在文件就不多赘述了。
  • 蓝框中的incl.是inclusive的简写。表示的是该函数及其内容所有函数的内容所占用的周期数。
  • 黄框中的self是exclusive的意味。即该函数中除去其他函数的内容所占用的周期数。
  • 绿框中的called是该函数在程序运行中调用的次数。

举例

  1. main()函数是主函数只运行一次,所以called=1。主函数肯定是包含程序的全部内容所以主函数incl占比无线接近百分百。但是主函数中一般包含别的函数,所以self占比往往非常低。
  2. 以粉色框为例,该函数运行1005次,总共占用43741422次。那么一次运行大概占用43523.8个cpu周期。

举例
在知道cpu周期数后,如何知道真正运行的时间呢?毕竟时间更加直观。
此处需要补充一些系统原理基本知识。
1个cpu周期=6个状态周期=12个节拍=12个震荡脉冲周期=12/震荡脉冲频率
只要能查到系统的震荡脉冲频率即可,一般机器的震荡脉冲频率有另一个叫法【cpu主频】
linux下可以通过如下指令查到

cat /proc/cpuinfo

我的cpuMhz为3192.079Mhz,那么一个cpu周期【cpu cycle/machine cycle】为3.759纳秒,如此便可以算出粉色框的函数单次运行时长为163.6微秒。与之前通过clock_gettime()函数计算得到的时间相近。
公式
t i m e = I n c l . c p u c y c l e c a l l e d ∗ 12 f r e q c p u . time= \frac{Incl._{cpu cycle}}{called}*\frac{12}{freq_{cpu}}. time=calledIncl.cpucyclefreqcpu12.

4.3kcachegrind补充

在摸索kcachegrind的过程中发现大部分都集中在看函数调用的树图,关于时间的计算和其他内容在百度或CSDN并没有过多描述,为此看了一上午,后来发现大部分内容在官网都是有描述。花费10到20分钟慢慢看一下官网,基本要找的信息全都找到了。
kcachegrind官网
工具是开源的,sourcecode和github上都可以跟踪。

5.其他工具

5.1Cachegrind

Cache分析器,它模拟CPU中的一级缓存和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
但是官网在程序优化中明确有建议程序不要过度优化,一般callgrind足够在代码效率上提供优化空间,所以cachegrind的使用概率较小,除非有明确的使用的场景。

使用方法:

valgrind –tool=cachegrind ./程序名

5.2Helgrind

它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发觉的错误。Helgrind实现了名为Eraser的竞争检测算法,并做了进一步改进,减少了报告错误的次数。不过,Helgrind仍然处于实验状态。
一般在做内存泄露的时候通常是使用memcheck,memcheck就已经能够覆盖多线程工作的情况,helgrind提供的是线程竞争的检测能力,这个检测不一定代表内存会泄露,但是也会出现程序运行结果不满足预期的问题。由于helgrind还在完善中,所以不是非常推荐使用,遇到多线程结果不满足预期,但也没有内存泄露的情况下,可以考虑进行分析。报告仅供参考,还是需要技术人员进一步自行分析。
或者可以找找看有没有开发比较完善的同类型分析工具
使用方法:

valgrind --tool=helgrind ./程序名

5.3Massif【亟待补充】

堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。

Massif对内存的分配和释放做profile。程序开发者通过它可以深入了解程序的内存使用行为,从而对内存使用进行优化。这个功能对C++尤其有用,因为C++有很多隐藏的内存分配和释放。
由于目前项目采用c++开发,所以在内存的分配和释放上如果希望更进一步,可以进行使用,同时也提供了一个更加便利的堆栈管理,相比于传统指令查看。
后续最好可以深入研究一下,或者可以找找看有没有开发比较完善的同类型分析工具

5.4其他

此外,lackey 和 nulgrind 也会提供。Lackey 是小型工具,很少用到;Nulgrind 只是为开发者展示如何创建一个工具。这里就不做介绍了。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值