如何减少模板繁重的C++代码的输出大小

How to reduce output size of template-heavy C++ code?

本文关键字:C++ 代码 输出 何减少      更新时间:2023-10-16

我遇到了一个大问题。我有一个通用库,在我的整个项目中都在使用。该库集中使用boost.spiritboost.fusion。不幸的是,该库的大小约为700Mb。所有的boost.spirit重代码都被使用了,并且运行良好。可以采取哪些步骤来减少其输出大小?有没有一种工具可以帮助确定哪些模板实例化浪费了大部分空间?

起初,我决定将所有意识到精神的代码移到cpp文件中。其次,我将尝试不同的编译器标志来优化大小。我不知道还能做什么。

更新(详细信息)

我使用的是GNU工具链。巨大的图书馆实际上是一个静态图书馆。使用这个700Mb库的可执行文件大小为200Mb。至少有一半的代码在*.h文件中。一些boost.spirit语法(非常重模板的东西)也位于*.h文件中。

干杯!

将spirit-aware代码移动到.cpp文件是一个很好的第一步,尽管您提到在头文件中有spirit语法,但这可能是不完整的。

  1. 确保任何语法/规则都不会导出到库外。如果您有典型的include/src目录,那么在src目录中移动这些文件(即使是头文件)。

  2. 将所有这些符号标记为库内部符号。他们根本不应该从图书馆外进入。根据编译器的不同,有特定的杂注/属性,在gcc查找可见性属性时:__attribute__ ((visibility ("internal")))。这有助于编译器相应地优化它们,特别是编译器可能会发出函数的代码,即使它在给定的调用位置内联函数,以防该函数地址被占用。然而,在内部可见性的情况下,由于它知道代码不会离开对象,因此可能会省略该函数。

  3. 我似乎记得有一面旗帜可以融合相同的功能体,但似乎再也找不到了。。。

--ffunction-sections将把每个函数放在自己的段中。这本身并不有用,但链接器可以使用--gc-sections删除未使用的部分。现在,如果没有--ffunction-sections,这只有在整个源文件未使用的情况下才能工作,即具有疯狂的粒度。

显然,您需要Matthieu提到的visibility属性,否则库中的所有函数都会因为可见而被"使用"。

这里已经讨论过:为什么我的C++输出可执行文件这么大?

基本上,查找调试符号、链接依赖关系的顺序、优化等等。。。

几个建议:

  • 在可能的情况下,尝试重用相同的模板实例化(作为一个简单而人为的例子,std::vector<int>std::vector<float>将具有相同的内部结构,并且都可以将它们的元素数据视为不透明的4字节Blob,因此一个可以委托给另一个,并且只充当一个东西包装器,它只会强制转换回正确的类型,因此向量的内部只需要实例化一种类型,而不是两种类型

  • 请尝试其他编译器。一些编译器在不会影响程序语义的地方重用相同的模板实例化,而另一些则更保守。

  • 密切关注从库中导出的内容。链接器可以删除未导出且未在内部引用的符号。(当然,如果你正在构建一个静态库,只有当它链接到一个可执行文件中时,这才会生效。为了减少库本身的大小,你可以尝试将其变成一个动态库。)

但最终,听起来你可能只需要使用一个模板较少的库。(或者编写一个比目前更简单的解析器)