profiling的使用
GNU gprof能够打印出程序运行中各个函数消耗的时间,可以帮助程序员找出众多函数中耗时最多的函数。产生程序运行时候的函数调用关系,包括调用次数,可以帮助程序员分析程序的运行流程。有了函数的调用关系,这会让开发人员大大提高工作效率
gprof的基本用法:
1.使用 -pg选项编译和链接你的应用程序,在makefile中加。
2.执行你的应用程序使之生成供gprof分析的数据,运行可执行程序:./ v2vapp_m_v2v,这样就生成了一个gmon.out文件,该文件就包含了profiling的数据。
注意:程序运行并“正常”退出后,会生成一个gmon.out文件。也就是说,程序必须是从exit或者return终止的。
例如:在我们的工程里面,可以在session.cpp中的session_run里面加限制条件,比如打算看100S中各个函数使用情况:可加gettimeofday(&pro_num_old,NULL);在while(1)前面;
gettimeofday(&pro_num_new,NULL);在while(1)里面。然后如下
if((pro_num_new.tv_sec - pro_num_old.tv_sec) > 100)
{
printf("new = %d, old = %d\n", pro_num_new.tv_sec, pro_num_old.tv_sec);
break;
}
3. 分析生成结果
gprof [Options] <可执行文件> <profiler data file>。
如:gprof v2vapp_m_v2v gmon.out > profile.txt
附:
gprof产生的信息
% the percentage of the total running time of the
time program used by this function.
函数使用时间占所有时间的百分比。
cumulative a running sum of the number of seconds accounted
seconds for by this function and those listed above it.
函数和上列函数累计执行的时间。
self the number of seconds accounted for by this
seconds function alone. This is the major sort for this
listing.
函数本身所执行的时间。
calls the number of times this function was invoked, if
this function is profiled, else blank.
函数被调用的次数
self the average number of milliseconds spent in this
ms/call function per call, if this function is profiled,
else blank.
每一次调用花费在函数的时间microseconds。
total the average number of milliseconds spent in this
ms/call function and its descendents per call, if this
function is profiled, else blank.
每一次调用,花费在函数及其衍生函数的平均时间microseconds。
name the name of the function. This is the minor sort
for this listing. The index shows the location of
the function in the gprof listing. If the index is
in parenthesis it shows where it would appear in
the gprof listing if it were to be printed.
函数名
valgrind的使用
Valgrind能做什么?
?内存使用检测,包括:
–内存泄漏
–非法内存访问
–未初始化变量使用
–重复释放内存
?多线程竞争
–检测死锁
-检测竞争
Valgrind还能做什么?
?性能分析
–Cachegrind+ cg_annotate
它模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数,这些可以看成程序的执行成本。以上数据其实对于app开发意义不大,仅作为参考。
使用方法:
–Callgrind+ callgrind_annotate/kcachegrind
比起Cachegrind而言Callgrind更有用。Callgrind在Cachegrind基础上实现,可以可视化展示函数调用关系,以及每个函数在整个进程运行过程中所占的成本。对于
?Helgrind/DRD
–POSIXAPI误用
–潜在的死锁提醒
–数据竞争
?Massif
–内存分析工具,统计进程使用的内存情况,包括堆、栈
Valgrind—— memcheck
用法:valgrind--tool=memcheck--leak-check=yes ./grog
输出:
Memcheck 工具主要检查下面的程序错误:
使用未初始化的内存 (Use of uninitialised memory)
使用已经释放了的内存 (Reading/writing memory after it has been free’d)
使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
malloc/free/new/delete
申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
Callgrind
Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
Cachegrind
它模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
Helgrind
它主要用来检查多线程程序中出现的竞争问题。Helgrind 寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为” Eraser” 的竞争检测算法,并做了进一步改进,减少了报告错误的次数。
Massif
堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。
Valgrind 安装1、 到www.valgrind.org下载最新版valgrind-3.2.3.tar.bz2
2、 解压安装包:tar –jxvf valgrind-3.2.3.tar.bz2
3、 解压后生成目录valgrind-3.2.3
4、 cd valgrind-3.2.3
5、 ./configure
6、 Make;make installValgrind 使用
用法: valgrind [options] prog-and-args [options]: 常用选项,适用于所有Valgrind工具
-tool=<name> 最常用的选项。运行 valgrind中名为toolname的工具。默认memcheck。
h –help 显示帮助信息。
-version 显示valgrind内核的版本,每个工具都有各自的版本。
q –quiet 安静地运行,只打印错误信息。
v –verbose 更详细的信息, 增加错误数统计。
-trace-children=no|yes 跟踪子线程? [no]
-track-fds=no|yes 跟踪打开的文件描述?[no]
-time-stamp=no|yes 增加时间戳到LOG信息? [no]
-log-fd=<number> 输出LOG到描述符文件 [2=stderr]
-log-file=<file> 将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID
-log-file-exactly=<file> 输出LOG信息到 file
-log-file-qualifier=<VAR> 取得环境变量的值来做为输出信息的文件名。 [none]
-log-socket=ipaddr:port 输出LOG到socket ,ipaddr:port
LOG信息输出
-xml=yes 将信息以xml格式输出,只有memcheck可用
-num-callers=<number> show <number> callers in stack traces [12]
-error-limit=no|yes 如果太多错误,则停止显示新错误? [yes]
-error-exitcode=<number> 如果发现错误则返回错误代码 [0=disable]
-db-attach=no|yes 当出现错误,valgrind会自动启动调试器gdb。[no]
-db-command=<command> 启动调试器的命令行选项[gdb -nw %f %p]
适用于Memcheck工具的相关选项:
-leak-check=no|summary|full 要求对leak给出详细信息? [summary]
-leak-resolution=low|med|high how much bt merging in leak check [low]
-show-reachable=no|yes show reachable blocks in leak check? [no]
注:5和6最好按照红色部分执行
1、下载最新版valgrind-3.8.1.tar.bz2
2、解压安装包:tar –jxvf valgrind-3.8.1.tar.bz2
3、解压后生成目录valgrind-3.8.1
4、 cd valgrind-3.7.0
5、vim configure(把armv7*改为arm*) ./configure –host=arm-hisiv200-linux
由于会出现下面12所说的错误,做修改:
Vim configure添加如下几行:
export PATH=$PATH:/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin
CC=arm-hisiv200-linux-gcc
CFLAGS=-I/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/usr/include
LDFLAGS=-L/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/usr/lib
然后make distclean; ./configure --prefix=/mnt/valgrind --host=arm-hisiv200-linux
6、 Make;(这里执行make install会出现找不到arm-hisiv200-linux-gcc的情况,所以没执行)
Make install
7、cp coregrind/valgrind /tftpboot/( tftpboot是挂载在板子上的)
cp memcheck/memcheck-arm-linux /tftpboot/(前四步是在ubuntu上操作)
8、在板子的/usr/local中mkdir lib;cd lib;mkdir valgrind
9、把memcheck-arm-linux放到/usr/local/lib/valgrind/下
10、在/etc/profile下加export PATH=$PATH:/mnt
11、valgrind ls –l会出现
==980== Memcheck, a memory error detector
==980== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==980== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==980== Command: ls -l
==980==
valgrind: Fatal error at startup: a function redirection
valgrind: which is mandatory for this platform-tool combination
valgrind: cannot be set up. Details of the redirection are:
valgrind:
valgrind: A must-be-redirected function
valgrind: whose name matches the pattern: memcpy
valgrind: in an object with soname matching: ld-linux.so.3
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux.so.3
valgrind:
valgrind: Possible fixes: (1, short term): install glibc's debuginfo
valgrind: package on this machine. (2, longer term): ask the packagers
valgrind: for your Linux distribution to please in future ship a non-
valgrind: stripped ld.so (or whatever the dynamic linker .so is called)
valgrind: that exports the above-named function using the standard
valgrind: calling conventions for this platform. The package you need
valgrind: to install for fix (1) is called
valgrind:
valgrind: On Debian, Ubuntu: libc6-dbg
valgrind: On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo
valgrind:
valgrind: Cannot continue -- exiting now. Sorry.
12、修改烧到板子上面的文件系统中的/lib目录下面的.so文件,因为编译出来的库文件是经过载剪的:
在/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/lib/目录下面的库文件是未经过裁剪的标准C库,把这里面的库文件替换烧到板子上面的文件系统中的/lib目录下面
添加default.supp、vgpreload_core-arm-linux.so到/usr/local/lib/valgrind
但还是会出现诸如下面的错误:
……
Conditional jump or move depends on uninitialised value(s)
==1006== at 0x4922160: strcmp (in /lib/libc-2.11.1.so)
==1006==
==1006== Conditional jump or move depends on uninitialised value(s)
==1006== at 0x4922778: strlen (in /lib/libc-2.11.1.so
……