原贴:http://www.it414.com/show/10099
Linux下检查内存泄漏、系统性能的系列工具
Pub Date:2008-02-16 10:45:34 Author: moon Click:164
在我先前的博客文章中我介绍了如何在Windows .NET环境下如何定位内存泄漏问题,今天我就来介绍一个在Linux下定位此类问题的工具Valgrind和Callgrind,以及基于Callgrind分析结果的GUI分析工具KCachegrind。Callgrind和KCachegrind在后面的专题讲。
首先介绍Valgrind,网址是:http://valgrind.org/,简述如下:
With the tools that come with Valgrind, you can automatically detect many memory management and threading bugs, avoiding hours of frustrating bug-hunting, making your programs more stable.
Valgrind是一个工具集,目前包括如下工具:
- Memcheck,主要是针对C/C++程序,所有对内存的读写均被其检查,所以调用malloc/new/free/delete等操作均为截获。错误发生时,Memcheck会立即报告相关源代码行号,以及调用函数。Memcheck的寻址能力是字节级,对于内存初始化的追踪可以达到比特级。在Memcheck下运行待检测程序,速度会比正常慢10到30倍。
- Addrcheck,是Memcheck的轻量级版本,它不作内存初始化的检查,所以它检测的错误少一些,但效率是前者2倍,是正常程序运行时间的5到20倍的样子。
- Cachegrind,是一个Cache的仿真检视器,它在CPU上对I1,D1和L2级的Cache进行了细致的仿真,所以它可以精确地查明代码中Cache流失的来源。它可以识别Cache流失的数量,内存索引的数量,每一行代码执行的指令的数量,并且可以提供每一个函数,模块,以及整个程序的总结。它对于任何语言都是有用的,
Cachegrin加载程序运行起来,会是平时时间的20到100倍长。
- Massif,是堆Heap的仿真检视器,它对程序堆状况定时来取一次快照,并且产生一个随时间变化的堆的开销图,其中还指示出了哪些程序分配了哪些堆空间。Massif加载程序会是平时时间的20倍之慢。
- Helgrind,是用来发现多线程程序的数据资源竞争的调试器。它可以寻找被多个POSIX线程访问的内存空间,但除过哪些没有用(pthread_mutex_) 线程信号量加锁的内存空间。它可以指示出线程间的不同步,并且发现很难发现的时间依赖问题。
Valgrind安装指南参考:
http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/valgrind.html
Valgrind的Memcheck使用举例:
假定你当前的程序,myprog arg1 arg2
若使用Memcheck,命令如下:
valgrind --leak-check=yes myprog arg1 arg2
Memcheck是Valgrind的缺省工具。--leak-check选项将打开内存泄漏的详细检测器。
如果说你的内存泄漏错误代码,即myprog如下所示:
1 #include <stdlib.h> 2 3 void f(void) 4 { 5 int* x = malloc(10 * sizeof(int)); 6 x[10] = 0; // problem 1: heap block overrun 7 } // problem 2: memory leak -- x not freed 8 9 int main(void) 10 { 11 f(); 12 return 0; 13 }
运行过程中,问题1的错误指示消息将会显示出来,主要是内存越界
==19182== Invalid write of size 4
==19182== at 0x804838F: f (example.c:6)
==19182== by 0x80483AB: main (example.c:11)
==19182== Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd
==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182== by 0x8048385: f (example.c:5)
==19182== by 0x80483AB: main (example.c:11)
对于问题2,内存泄漏的消息如下所示:
==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182== by 0x8048385: f (a.c:5)
==19182== by 0x80483AB: main (a.c:11)
怎么样?这里只是一个非常简单的例子,你不妨可以一试。
2、系统性能瓶颈的分析工具
这一节我们主要讲两个关联在一起的系统性能瓶颈的分析工具Callgrind和KCachegrind。这两个工具的主页是:http://kcachegrind.sourceforge.net/cgi-bin/show.cgi
Callgrind是程序运行状况的检视器,它以前叫Calltree。KCachegrind是运行状况的显示器。Callgrind使用了我们前面讲的Valgrind架构的Cache仿真监测和呼叫图的生成部分。这样的话,即使是共享库,以及动态调用的插件也会被俘获到。Callgrind生成的数据分析文件可以被KCachegrind加载以图形化的方式显示出来。
在Suse环境下分别独立编译安装Callgrind和KCachegrind既费力又费事,下面我介绍一种简单的办法,首先使用Yast2来Update你的当前软件包,具体操作参加下文:
http://www.novell.com/coolsolutions/feature/11504.html
但文中的参数不对,你可以从Novel的FTP镜像服务器列表中灵活选择:
http://www.novell.com/products/suselinux/downloads/ftp/int_mirrors.html
我使用的服务器参数是:mirrors.kernel.org,路径是/suse/i386/9.2
然后你在Yast中搜索kdesdk3-profile,安装即可。
或者你可以从Novell对Suse9.2的近期KDE应用的列表中下载RPM自行安装也可以
http://www.novell.com/linux/download/linuks/x86_64/update_for_9_2/extra.html
看到kdesdk3-profile就是我们要找的,其描述如下:This package contains KCachegrind and the needed Calltree skin for Valgrind. You can profile your application with Valgrind using Calltree skin and display the result in KCachegrind to easily find bottlenecks.
直接下载地址是:ftp://ftp.suse.com/pub/suse/x86_64/supplementary/KDE/update_for_9.2/applications/.link/kdesdk3-profile.rpm
如果你自行手动编译安装,请参考:http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindInstallation
安装完后,下面我就来讲讲如何使用这两个工具:
首先用Callgrind来加载我的应用程序myprog, 命令是callgrind myprog,系统运行完后,或者自己使用Ctrl+C强制停止后,系统会生成一个文件,格式如下:callgrind.out.pid
Callgrind还用很多复杂的应用,可以参见:http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindUsage,这里不再详述。
下面介绍一下KCachegrind对输出的数据文件的分析图,下面是一个参考图,该图中包含三个子视图,Cost Type View, Call Graph View and Callee Map View。
在Callee Map View中,你能看到每一个函数的开销百分比包括Inclusive,即涵带子函数的总开销和Self,函数自己的开销,另外每一个函数的调用次数也列写在上面。
在Cost Type View中,每一个函数通过调用关系以模块的形式表现出来,往往在这里,通过显示的模块大小,并且结合Callee Map View中的函数Self开销,可以发现系统中的瓶颈函数。这点非常实用。
最后一个Call Graph View可以分析出函数的调用关系和流程,这是一个非常好的辅助工具,帮助你快速理解系统的工作流Work Flow。