对C ++编译过程进行性能分析


78

我倾向于编写相当大的仅模板头的C ++库模板,而我的用户通常抱怨编译时间。在考虑了这个问题之后,我想到我不知道时间在哪里。是否有一些简单的方法可以用通用编译器(例如g ++,icc和xlC)来分析C ++编译过程?例如,是否有可能了解在C ++编译的每个阶段中花费了多少时间?



2
@KarthikT我很欣赏这个建议,但是我对更多的细粒度信息(以及更广泛的编译器)感兴趣。例如,如果我从仅标头的库中构建一个目标文件,如何查看时间?
Jack Poulson

我知道,我找不到比这更细的东西了,对不起。
Karthik T 2012年

Answers:


65

对于GCC,可以找到调试选项how much time is spent within each of the phases of C++ compilation?

-Q 使编译器在编译时打印出每个函数名称,并在完成时打印有关每个遍历的一些统计信息。

-ftime-report 使编译器打印一些有关每次遍历完成时所消耗时间的统计信息。

传递在GCCINT 9:传递和编译器文件中进行了描述

您可以-v -ftime-report在此处发布单个源文件的g ++编译输出,以进行讨论。GCC邮件列表上可能会有帮助。


对于除GCC(或比3.3.6更古老的GCC )以外的编译器,请参见此线程中的其他选项。


2
PS:-Q可以通过某些awk或perl脚本来获取,解析和分析输出;或者您可以只看控制台上的函数名称打印,长时间暂停后打印的所有内容都很难编译。
osgx 2015年

任何想法如何将定时附加到函数名称上(缺少g ++)?我有一个200 MB的文件,带有一些意大利面条式的功能,不知道哪个功能需要很长时间才能编译。它们大多数都是快速编译的,其中只有很多(这也是模板繁重的代码)。我当时在想管道和脚本,但是管道有一些缓冲区,短名称的函数可能要等到更多的时候才能到达那里。

1
猪,尝试在gcc / cgraphunit.c中grep'quiet_flag'和gcc/toplev.cannounce_function -“解析函数定义的开始时,此函数在stderr上打印函数的名称”)。这announce_function可能是添加打印时间戳记(gettimeofday)或以某种非缓冲方式重写输出的关键。或者另一种可能的方式是启用调试转储(-fdump-rtl-all-all -fdump-tree-all-all -fdump-ipa-all-all),但它们每遍将输出1个文件;您需要将它们转换为每个遍历和每个函数输出1个文件(随着创建时间获得很多文件)。
osgx

14

一个工具来自Boost的项目,可为几乎任何编译器和构建系统是有用的。

该工具需要通过和宏调用进行源代码检测。然后,这些宏在编译时生成特定的诊断(警告),并通过脚本将其与实例化调用堆栈(因此允许构建和可视化调用图)一起计时并收集。不错,IMO。TEMPLATE_PROFILE_ENTER()TEMPLATE_PROFILE_EXIT()

我还没有用过。


在其文档页面中,我看不到需要源代码检测。你在哪里读的?
lrineau 2014年

@Irineau,在源中。该工具还提供了一些脚本,这些脚本似乎可以自动执行即时检测(尽管粒度未知)。
ulidtko 2014年

1
链接已死。
rustyx

好吧@rustyx,这也就不足为奇了,看到URL上的svn .boost.org和21世纪的时钟……有人上传了fork / mirror / rewrite?不过,也许有帮助。
ulidtko


5

您可以在一定程度上将它们分开(我假设是make

  • 添加仅对文件进行预处理的构建规则(使用-E开关),以及.PHONY依赖预处理器输出文件的目标,就像普通的二进制目标依赖.o文件一样。测量建立此目标需要多长时间
  • 添加一个'PHONY依赖于所有.o文件但不链接它们的目标。测量建立此目标所需的时间(从干净的角度看)
  • 测量完成通常的二进制文件的清洁所需的时间

现在您已经知道预处理,编译和链接需要多长时间。您还可以比较-O0第二个和第三个目标的优化和非优化()版本,以了解在优化器中花费了多长时间。


感谢您的答复。我认为这对于C程序来说已经足够了,但是对于不生成多个.o文件的仅标头C ++,几乎所有的时间都将花费在构建单个.o上。我对此表示反对,但会指责某人会提出更细粒度的方法。
Jack Poulson

嗯,所以您对翻译阶段没那么感兴趣,因为哪一段代码花费的时间最多?
没用

2
如果使用clang / llvm,则可以使用类似的技术将前端(clang)与后端(llvm-opt)分开。在后端,您甚至可以转储优化器图并单独运行它们。在gcc中,您可以比较-O0和-O3之间的构建时间,并查看优化时间与其他时间之间的差异。然后,您可以有选择地启用优化器,以查看最严重的违规者(如果有)。
Ze Blob 2012年

5

Clang 9(及更高版本)具有一个-ftime-trace标志,该标志使其可以将概要分析报告作为JSON输出(除目标文件之外)。

您可以将此文件导入Chrome(chrome://tracing)随附的探查器中,以直观呈现:

图片

这些条对应于必须解析的标头,并且对于每个标头,必须解析特定的类(可能还有其他构造)。它还报告花在实例化特定模板上的时间。


2

strace -e trace=process -f -r -ttt -T至少对于分解成许多进程的g ++之类的编译器,您也许可以通过on的某些变体来吸引一些人。


0

其他人已经建议使用-ftime-reportGCC的命令行标志,这使编译器可以打印一些有关每个编译阶段所用时间的统计信息。缺点是只显示一个单元的摘要。

我已经编写了一个Python脚本,该脚本可以在给定项目构建日志文件的情况下,在每个编译阶段按所有单位打印总摘要。它还允许按不同阶段排序。而且它还允许比较两个日志文件(例如,如果您试图了解更改的影响)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.