如何测量pimpl候选人?

时间:2016-02-27 12:36:13

标签: c++ profiler pimpl-idiom

pimpl(也称为编译器防火墙)习惯用于缩短编译时间,但代价是可读性和一点运行时性能。目前项目需要很长时间才能编译,如何衡量最佳pimpl候选人?

我有使用pimpl的经验,将项目的编译时间从两小时缩短到十分钟,但我只是按照我的直觉做了这个:我推断出包含(1)很多源代码的类头文件( 2)复杂/模板类,是使用疙瘩成语的最佳人选。

是否有一个工具可以客观地指出哪些类是优秀的pimpl候选人?

2 个答案:

答案 0 :(得分:0)

Pimpl对增量编译很有用。

但使用Pimpl的主要原因是为了保持ABI兼容性。这是我过去公司对API中几乎所有公共类的规则。

其他优点是您还可以将库分发为包含不暴露实现细节的标头的包。

为此我会说:尽可能使用Pimpl。

Qt Pimpl实施细节及其优点的一篇非常好的文章:https://wiki.qt.io/D-Pointer

编译时问题必须通过以下方式解决:

  • 使用预编译标题
  • 通过代码触摸频率将您的大项目划分为小项目。不经常更改的部件可以在库中编译并发布到本地存储库中,其他项目按版本引用。
  • ...

答案 1 :(得分:0)

我不知道现有的工具可以执行此操作,但我建议:

首先,衡量包括每个标头本身的独立成本。列出所有标题,并对每个标题进行预处理。标头成本的最简单度量是预处理产生的行数。可能更准确的方法是计算“模板”的发生,因为根据我的经验,处理模板定义似乎在编译时间中占主导地位。您还可以计算“内联”的出现,因为我已经看到在标头中定义的大量内联函数也是一个问题(但请注意,类方法的内联定义不一定使用关键字)。

接下来,测量包含该标头的翻译单元(TU)的数量。对于TU的每个主文件(例如.cpp文件),请对该文件进行预处理,并收集出现在输出中的#行中的不同标头集。然后,将其反转以获取从标头到使用它的TU数量的映射。

最后,对于每个标头,将其独立成本乘以包含它的TU数量。这是此头文件对总编译时间的累积影响的度量。对该列表进行排序并以降序浏览,将私有实现的详细信息移动到关联的实现文件中,并相应地修剪公共头。

现在,使用这种方法或任何此类方法来衡量私有实现的好处的主要问题是,一开始您可能不会看到太大的变化,因为在没有工程规范的情况下,通常会有很多标头其中包括许多其他项目,并且有很多重叠之处。因此,优化一个频繁使用的标头将仅意味着包含几乎相同数量的其他频繁使用的标头将使编译时间变长。但是,一旦您突破了具有许多依赖关系的常用头文件的临界质量,对大多数或全部头文件进行了优化,编译时间就会开始急剧下降。

一种集中精力的方法是,首先选择一个花费最多时间进行编译的TU,然后仅优化它所依赖的头文件,因此它并不是“天上掉馅饼”。一旦您大大减少了该TU的时间,请再次查看全局。而且,如果您不能通过私有实现技术来显着改善一个TU的编译时间,则表明您需要针对该代码库考虑其他方法。