如何找到在Linux上运行的C++应用程序中运行缓慢的代码区域?
当前回答
使用具有以下选项的Valgrind:
valgrind --tool=callgrind ./(Your binary)
这将生成一个名为callgrind.out.x的文件。使用kcachegrind工具读取该文件。它会给你一个图形化的分析结果,比如哪一行花费多少。
其他回答
如果没有一些选项,运行valgrind--tool=callgrind的答案并不完全。我们通常不希望在Valgrind下描述10分钟的缓慢启动时间,而希望在执行某些任务时描述我们的程序。
这就是我的建议。首先运行程序:
valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp
现在,当它工作并且我们想要开始评测时,我们应该在另一个窗口中运行:
callgrind_control -i on
这将打开分析。若要关闭并停止整个任务,我们可以使用:
callgrind_control -k
现在,我们在当前目录中有一些名为callgrind.out.*的文件。要查看分析结果,请使用:
kcachegrind callgrind.out.*
我建议在下一个窗口中单击“Self”列标题,否则它会显示“main()”是最耗时的任务。“Self”显示每个函数本身花费的时间,而不是与依赖项一起花费的时间。
您可以使用loguru这样的日志框架,因为它包括时间戳和总运行时间,可以很好地用于分析:
这是对Nazgob Gprof回答的回应。
过去几天我一直在使用Gprof,已经发现了三个重要的限制,其中一个是我在其他地方还没有看到过的:
它不能在多线程代码上正常工作,除非您使用变通方法调用图被函数指针弄糊涂了。示例:我有一个名为multithread()的函数,它使我能够在指定的数组上对指定的函数进行多线程处理(两者都作为参数传递)。然而,Gprof将所有对多线程()的调用视为等效的,以计算在孩子身上花费的时间。由于我传递给多线程()的一些函数花费的时间比其他函数长得多,所以我的调用图基本上是无用的。(对于那些想知道线程是否是这里的问题的人来说:不,多线程()可以选择,在这种情况下,只在调用线程上按顺序运行所有内容)。这里说“……调用数数字是通过计数而不是采样得出的。它们是完全准确的……”。然而,我发现我的调用图给了我5345859132+784984078作为对我调用最多的函数的调用统计数据,其中第一个数字应该是直接调用,第二个递归调用(都来自它本身)。因为这意味着我有一个bug,所以我在代码中加入了长(64位)计数器,并再次运行相同的程序。我的计数:5345859132个直接调用和78094395406个自递归调用。这里有很多数字,所以我要指出,我测量的递归调用是780亿,而Gprof是7.84亿:相差100倍。两次运行都是单线程和未优化的代码,一次是编译的-g,另一次是-pg。
这是在64位Debian Lenny下运行的GNUGprof(Debian的GNUBinutils)2.18.0.20080103,如果这对任何人都有帮助的话。
使用Valgrind、callgrind和kcachegrind:
valgrind --tool=callgrind ./(Your binary)
生成callgrind.out.x。使用kcachegrind读取它。
使用gprof(add-pg):
cc -o myprog myprog.c utils.c -g -pg
(对于多线程、函数指针不太好)
使用google perftools:
使用时间采样,可以发现I/O和CPU瓶颈。
英特尔VTune是最好的(出于教育目的免费)。
其他:AMD Codeanalysis(已被AMD CodeXL取代)、OProfile、“perf”工具(apt-get-install-linux工具)
对于单线程程序,您可以使用igprof,The Ignorminous Profiler:https://igprof.org/ .
这是一个采样分析器,沿着。。。长的Mike Dunlavey的回答,它将把结果包装在一个可浏览的调用堆栈树中,用每个函数(无论是累积的还是每个函数)花费的时间或内存进行注释。
推荐文章
- decltype(auto)的一些用途是什么?
- Shared_ptr转换为数组:应该使用它吗?
- Printf与std::字符串?
- 在Bash中检查变量是否存在于列表中
- 禁用复制构造函数
- 查看PS命令的全部输出
- 只接受特定类型的c++模板
- c#和Java中的泛型有什么不同?和模板在c++ ?
- Linux命令将域名转换为IP
- c++ 11中的递归lambda函数
- 在c++中指针使用NULL或0(零)吗?
- 在c++中,如何将int值附加到字符串中?
- 如何从命令行在windows中找到mysql数据目录
- 就性能而言,使用std::memcpy()还是std::copy()更好?
- 为什么布尔值是1字节而不是1位?