C ++通过使用库

时间:2017-10-04 07:01:07

标签: c++ windows performance dll libraries

我目前正在尝试优化大型项目的构建速度,并牢记以下:

  • 构建速度优先级为1
  • 生成的二进制文件大小重要

的相关信息:

  • 环境:Visual Studio 2012(需要,因为我正在开发的软件)+ Windows机器
  • 构建时间:12分钟(干净的构建),1分钟进行小的更改,现在每个小的更改都会导致5-6分钟因为链接速度慢(这是我要解决的问题)
  • 项目中的自定义文件:约。 2500(SDK我需要使用排除,一个用于CAD系统的大SDK)
  • 自定义文件中的代码行:约。 500000
  • 我正在使用最新的支持CAD的计算机(32GB RAM,> 3GHz QuadCore,SSD)

思路:

  • 使用预编译的标头=>完了,但没有我想要的效果;有助于在大多数时间加快编译时间,但现在每一次都没有
  • 将项目拆分为库=>不确定这是否有帮助

问题

我找不到有关使用库和构建速度的任何内容,但我认为如果我预编译库,链接器会更快。

  • 这个假设是真的吗?
  • 如果我创建一个带有核心功能的静态库,这会对构建时间产生影响吗?或者链接器是否需要与目前一样长的时间?
  • 如果我创建一个动态库,这会对构建时间产生影响吗?或者链接器是否会再次检查dll并且需要相同的时间?

2 个答案:

答案 0 :(得分:1)

12分钟是完整的建设时间,而500KLOC并不是那么大。许多自由软件项目(GCC,Qt,...)有更长的时间(小时)和数百万的C ++行。

您可能希望使用严谨且并行的build automation工具,例如ninja。如果你可以在远程机器上编译,也许你可以做一些分布式构建(比如distcc允许的那样)。

您可以将IDE配置为针对构建运行外部命令(例如ninja)。这不会改变自动完成功能。您可以采用其他source code editor(例如GNU emacs)。

C ++不是(尚未)模块化(它没有真正的模块,例如Ocaml或Go),这使得编译速度变慢(例如,因为标准容器头很大,例如<vector>带来了大约10KLOC包含的代码,可能在大多数C ++代码中使用,包含。所以你应该避免使用许多小文件(例如,将两行250行中的两个文件合并为500行中的一行可能会减少构建时间),看起来你有太多小的C ++文件。我建议源文件超过一千行。每个源文件只有一个类实现(或一个函数)会减慢总构建时间。

您肯定希望在代码中使用更多间接。更系统地使用PIMPL成语和virtual method tables,闭包,std::function - s。请记住rule of five

答案 1 :(得分:1)

  

我假设如果我预编译库,链接器会更快。这个假设是真的吗?

不,不太可能。如果有的话(因为链接器必须打开更少的文件),那么差异将是边缘的。

  

如果我创建一个带有核心功能的静态库,这会对构建时间产生影响吗?或者链接器是否需要与目前一样长的时间?

它可能会对编译时间产生巨大影响,因为虽然在真正干净的重建中你仍然需要像以前一样编译所有东西,在正常的“大多数干净”的重建中重建支持库是多余的因为它们内部没有任何变化,所以你真正需要重建的就是用户代码,因此你可以编译更少的文件。
请注意,每个合理的构建系统通常都会构建一个依赖关系图,并尝试尽可能少地编译文件(并且尽可能地以某种程度的并行性编译),除非您明确地告诉它要做干净的构建(很少需要完成)。医生,我这样做很痛 - 好吧,不要这样做。

链接器的差异再次是微不足道的。链接器仍然需要查找完全相同数量的符号,并且仍然需要将相同数量的代码复制到可执行文件中。

您可能想玩链接顺序。听起来很有趣,有时库和目标文件的链接顺序会使链接器完成工作所需的时间差异为5倍。

话虽这么说,干净的构建12分钟确实不是很多。您的非清洁建筑可能会在两位数的第二范围内,其中链接可能需要90%。这通常不是一个表明。当构建需要4个小时时回来: - )

  

如果我创建一个动态库,这会对构建时间产生影响吗?或者链接器是否会再次检查dll并且需要相同的时间?

链接器仍然需要为你调用的每个函数做一些工作,这些函数可能稍微更快,但仍然或多或少相同。

请注意,通过将代码移动到DLL中来添加运行时(启动)开销。加载器在DLL中加载程序包含部分代码是更多的工作,因为它需要加载另一个图像,解析其标题,解析符号,设置一些指针,运行每线程初始化函数等。这通常是不是问题(差异并不是那么明显),只是让你知道它不是免费的。