综述
- gprof用于分析函数调用耗时,可用之抓出最耗时的函数,以便优化程序。
- gcc链接时也一定要加-pg参数,以使程序运行结束后生成gmon.out文件,供gprof分析。
- gprof默认不支持多线程程序,默认不支持共享库程序。
- gcc -pg 编译程序
- 运行程序,程序退出时生成 gmon.out
- gprof ./prog gmon.out -b 查看输出
注意事项
- 程序如果不是从main return或exit()退出,则可能不生成gmon.out。
- 程序如果崩溃,可能不生成gmon.out。
- 测试发现在虚拟机上运行,可能不生成gmon.out。
- 一定不能捕获、忽略SIGPROF信号。man手册对SIGPROF的解释是:profiling timer expired. 如果忽略这个信号,gprof的输出则是:Each sample counts as 0.01 seconds. no time accumulated.
- 如果程序运行时间非常短,则gprof可能无效。因为受到启动、初始化、退出等函数运行时间的影响。
- 程序忽略SIGPROF信号!
原理
gcc -pg 在应用程序的每个函数中添加了名为 mcount/mcount/_mcount的函数。 应用程序每个函数执行时都会执行mcount,而mcount则会在内存中保存一张函数调用图, 通过函数调用堆栈的形式,查找子函数、父函数的地址,也保存了与函数相关的调用时间、次数等信息。
多进程
如果用gprof分析多进程程序,则可能一个进程的gmon.out覆盖另一个进程的gmon.out, 解决方法是在执行程序之前执行:export GMON_OUT_PREFIX=x.out 则之后生成的文件名就如x.out.pid,多进程的gmon.out就不会相互覆盖。
多线程
gprof无法分析多线程程序。缘故是gprof使用ITIMER_PROF定时器, 当超时时由内核向应用程序发送信号。但多线程程序只有主线程接收ITIMER_PROF。 这里有一个简单的实现方法: 对pthread_create进行包装,并以动态库的形式在程序运行前加载。 我通过上文的描述,整理了一个gprof分析多线程程序的程序,可供参考。
<span class="pln" style="color: rgb(0, 0, 0);">$ gcc </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);">shared </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);">fPIC gprof_helper</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">c </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);">o ghelper2</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">so </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);">lpthread </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);">ldl </span><span class="com" style="color: rgb(136, 0, 0);"># create ghelp2.so</span><span class="pln" style="color: rgb(0, 0, 0);"> $ gcc test</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">c </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);">lpthread $ </span><span class="pun" style="color: rgb(102, 102, 0);">./</span><span class="pln" style="color: rgb(0, 0, 0);">a</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pln" style="color: rgb(0, 0, 0);"> hello gprof </span><span class="com" style="color: rgb(136, 0, 0);"># output</