如何获取程序中每行代码的“执行时间”?

4
我刚刚使用了 gprof 来分析我的程序。我想看看哪些函数消耗了最多的 CPU 时间。不过现在,我想用另一种方式来分析我的程序。我想要看看哪些代码行消耗了最多的 CPU 时间。起初,我读到 gprof 可以做到这一点,但我找不到合适的选项。 现在,我找到了 gcov。然而,我正在尝试执行的第三方程序没有 "./configure",因此我无法应用 "./configure --enable-gcov"。 我的问题很简单。有人知道如何获取每行代码的执行时间吗? (我更喜欢使用 gprof,因为我发现它的输出非常易于阅读和理解。)
3个回答

4
我认为oprofile是你要寻找的东西。它采用基于统计的抽样方式,为你提供了一个大致的指示,告诉你每行代码执行所花费的时间,包括C抽象层次和汇编代码层次。
除了简单地对每行代码花费的相对周期数进行分析外,你还可以为其他事件(如缓存未命中和流水线停顿)进行仪器化。
最重要的是:你不需要为了进行性能分析而进行特殊的构建,只需要启用调试符号即可。
这里有一份关于oprofile的好介绍:http://people.redhat.com/wcohen/Oprofile.pdf

Oprofile没有安装在我们的服务器上,而且我没有安装它的权限。有其他方法可以逐行执行吗? - user598208
类似 oprofile 这样的工具需要访问性能计数器寄存器,因此最好在您自己的计算机或拥有超级用户访问权限的计算机上运行分析。如果无法实现这一点,您可能需要尝试与系统管理员协商获取访问权限。 - Anthony Blake
"perf" 是 oprofile 的替代品,不需要 root 权限即可使用,但它仅在相对较新的内核中可用(自 2.6.31 版本或类似版本开始)。 - janneb

1
如果您的程序执行时间不太长,Valgrind/Callgrind + KCacheGrind + [开启调试模式编译(-g)] 是如何确定程序在用户模式下花费时间的最佳方法之一。
valgrind --tool=callgrind ./program
kcachegrind callgrind.out.12345

在您要优化的部分中,该程序应具有稳定的IPC(每个时钟周期指令)。

缺点是Valgrind无法用于测量I/O延迟或配置内核空间的性能。此外,对于使用与C/C++工具链不兼容的编程语言的可用性也受到限制。

如果Callgrind对整个程序的插装执行时间过长,则可以使用宏CALLGRIND_START_INSTRUMENTATIONCALLGRIND_STOP_INSTRUMENTATION

在某些情况下,Valgrind需要带有调试信息的库(例如/usr/lib/debug/lib/libc-2.14.1.so.debug),因此您可能需要安装提供调试信息文件的Linux软件包或重新编译启用了调试的库。


0

oprofile 可能如 Anthony Blake 所建议的那样是最好的答案。

然而,在编译一个 autoconf 的软件时,可以使用一个技巧来强制编译器或编译器标识(例如编译 gprof 分析所需的 -pg 标识)。

CC='gcc -pg' ./configure

或者

CFLAGS='-pg' ./configure

这对于一些新的编译模式也非常有用。例如,gcc 4.6提供了在编译和链接时传递 -flto 标志的 链接时间优化;为了启用它,我经常这样做:

CC='gcc-4.6 -flto' ./configure

对于一个没有使用自动配置的程序,但仍然使用合理的Makefile进行构建的情况下,你可以编辑该Makefile或尝试其他方法。
make CC='gcc -pg'

或者

make CC='gcc -flto'

它通常(但并非总是)有效。


谢谢您的回复,不幸的是,我得到的第三方代码没有 ./configure ... :( - user598208
жҲ‘дёәеҹәдәҺmakeзҡ„еҗҲзҗҶжһ„е»әж·»еҠ дәҶдёҖдёӘе»әи®®гҖӮ - Basile Starynkevitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接