[C++] 我如何分析在Linux中运行的C ++代码?


Answers

您可以使用Valgrind和以下选项

valgrind --tool=callgrind ./(Your binary)

它会生成一个名为callgrind.out.x的文件。 然后可以使用kcachegrind工具读取该文件。 它会给你一个结果的图形分析,比如哪条线要花多少钱。

Question

我有一个C ++应用程序,运行在Linux上,我正在优化。 我怎样才能确定我的代码的哪些区域运行缓慢?




这是对Nazgob的Gprof答案的回应 。

过去几天我一直在使用Gprof,并且已经发现了三个重要的限制,其中一个我还没有在其他地方见到过(还没有):

  1. 它在多线程代码上无法正常工作,除非您使用workaround

  2. 调用图被函数指针弄糊涂了。 示例:我有一个名为multithread()的函数,它使我能够在指定的数组上多线程指定的函数(都作为参数传递)。 但是,Gprof将所有对multithread()的调用视为等同于计算在儿童中花费的时间。 由于我传递给multithread()的一些函数比其他函数花费的时间长得多,所以我的调用图大多是无用的。 (对于那些想知道线程是否存在问题的人来说:no,multithread()可以选择,在这种情况下,只能在调用线程上按顺序运行)。

  3. here表示“......呼叫数字是通过计数而不是取样得出的,它们是完全准确的......”。 然而,我发现我的通话图给我5345859132 + 784984078作为我最常用的函数的调用统计,其中第一个数字应该是直接调用,第二个递归调用(全部来自它本身)。 由于这意味着我有一个错误,所以我在代码中放入了很长的(64位)计数器,并再次执行相同的操作。 我的计数:5345859132直接和78094395406自我递归调用。 这里有很多数字,所以我会指出我测量的递归调用是780亿,而Gprof则是784万:这是100个不同的因子。 两次运行都是单线程和未优化的代码,一次编译-g和另一个-pg。

这是在64位Debian Lenny下运行的GNU Gprof (GNU Binutils for Debian)2.18.0.20080103,如果这有助于任何人。




使用Valgrind,callgrind和kcachegrind:

valgrind --tool=callgrind ./(Your binary)

生成callgrind.out.x。 使用kcachegrind阅读它。

使用gprof(加上-pg):

cc -o myprog myprog.c utils.c -g -pg 

(对于多线程,函数指针不太好)

使用谷歌perftools:

使用时间采样,揭示I / O和CPU瓶颈。

英特尔VTune是最好的(免费用于教育目的)。

其他: AMD Codeanalyst,OProfile,'perf'工具(apt-get install linux-tools)




对于单线程程序,您可以使用igprof ,不明原因分析器: https://igprof.org/ ://igprof.org/。

它是一个采样分析器,沿着Mike Dunlavey的... long ...的答案,它将把结果包装在可浏览的调用堆栈树中,用每个函数花费的时间或内存进行注释,可以是累积的或每个函数。




较新的内核(例如最新的Ubuntu内核)带有新的'perf'工具( apt-get install linux-tools )AKA perf_events

这些配备了经典的采样分析器( man-page )以及令人敬畏的timechart

重要的是,这些工具可以是系统分析 ,而不仅仅是进程分析 - 它们可以显示线程,进程和内核之间的交互,并让您了解进程之间的调度和I / O依赖关系。