【问题标题】:Build Boost-powered solution in VS在 VS 中构建基于 Boost 的解决方案
【发布时间】:2010-11-26 15:40:33
【问题描述】:

Boost 非常棒,它很棒而且非常强大,但我每次在 Visual Studio 7.1 中构建解决方案时都讨厌它。

似乎 Boost 对构建时间有影响(不是正面的)。我无法从我的项目中删除所有 Boost 使用来比较构建时间,但我在小型项目上进行了尝试,并且差异很有意义。

我想问题在于 Boost 由数千个头文件组成,其中包含非常广泛的自身。因此,当我在头文件中包含 boost/function.hpp 时,可能会导致包含数百个 Boost 头。

有没有人有同样的经历?任何想法如何解决它?

粗略的想法:

  1. 为预编译的头文件添加增强?至少它们会被解析并保存在一个文件中
  2. 是否对某些 Boost 模板进行显式实例化?
  3. 以某种方式准备 Boost 标头?
  4. 不要在头文件中包含 Boost(听起来不真实)
  5. ...

PS。是的,Boost 还使用硬核模板,我猜这很难编译,所以成千上万的头文件不是唯一的问题。

【问题讨论】:

    标签: c++ visual-studio visual-c++ boost build-process


    【解决方案1】:

    我也喜欢提升很多

    • 按照您所说的那样使用预编译的头文件(这会带来最多)
    • 使用链接库时,检查您是否真的需要它们(链接也很慢)

    另一个可能很愚蠢的提示,但它是我计算机性能损失的主要来源:

    • 检查您的防病毒软件是否进行访问扫描并为标头和源目录(boost 和您的项目)禁用它

    【讨论】:

    • 为防病毒说明点赞!它们通常比病毒造成的危害更大。
    • 杀毒软件以前打过我。
    • 关于防病毒的好点,但它已经被禁用构建目录。我们还为项目文件和输出使用单独的 HDD。很有帮助。
    【解决方案2】:

    当然,包含 boost 会导致更长的编译时间 - 就像包含任何库一样。由于所有逻辑都在标头中实现,因此(主要)是模板库会导致相当大的性能损失。

    1. 我已经取得了很好的结果,包括预编译头文件中的(一个子集)提升。但是,我相信 MSVC 9 的收益最大。在 MSVC 7 上,我看到一些报告说模板的预编译标头经常会导致性能下降。确定您是否会看到性能提升的另一个关键方面是在预编译的标头中包含适当的标头。只包含您经常使用的标头,并确保它们永远不会更改(也就是说,在此处包含您自己的标头之前要三思而后行)

    2. 我不知道显式实例化是否有任何效果,尽管我对此表示怀疑。如果有人对此(无论编译器)有任何结果,那将非常有趣。

    3. “准备”提升标头听起来像是在更改它们,这对我来说是个非常糟糕的主意。您不想最终维护自定义标题...

    4. 可能并不像您想象的那么不真实。始终尽可能多地使用forward declarations,以减少每个头文件的“足迹”。考虑使用Pimpl 模式来避免包含未反映在类的公共接口中的 boost 标头(题外话:我认为 Pimpl 通常是不必要的。相反,我尝试将类切成更小的部分,从而在“更清洁”的时尚)。只要您在使用这些类时保持一致,就不要害怕包含通用的通用类(例如 shared_ptr)(如果您在所有类中都使用它们,那么将它们从一个标题中隐藏起来不会有太大的好处) .

    5. 升级 MSVC(以支持并行构建)会有所帮助。但是,这在 C++ 中始终是一个问题。为了最大限度地减少问题,您需要非常严格并遵循指南以减少标头的占用空间。有时您应该查看包含子句并确保没有包含任何不必要的内容。如果您在标题中完成的包含列表越来越长,您可能做错了什么 - 大多数包含应该在 cpp 中。

    【讨论】:

      【解决方案3】:

      仅在真正需要时才包含 Boost 头文件是有意义的。包含其他头的头对IO造成压力,对编译时间有很大影响。前向声明在某种程度上有所帮助,但使用 Boost 可能会很痛苦。

      在头文件中使用外部保护可以避免不必要的加载。像这样:

      #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
      #   include <boost/shared_ptr.hpp>
      #endif
      

      另一种避免标题级联的方法是使用"pimpl"-idiom,尤其是在处理复杂类时。然后可以包含复杂的 Boost 内容,并且只能由该编译单元使用。缺点是接口应该被设计成不需要 Boost 特定的东西。但是,打破依赖关系也可能是一件好事。

      【讨论】:

      • 如果不是您的代码,外部包含保护可能会有风险——Boost 是否保证他们不会更改包含保护格式?
      • 是的。他们可能有风险。有时即使它是您自己的代码。 :) 据我所知,并不能保证 Boost 标头守卫会保持这种状态。不过,我愿意承担这个风险。如果它们碰巧发生了变化,那只是一堆编译器错误,很容易指向未包含的文件。
      • 要么,要么你的优化方案被静默地破坏,因为你正在检查 BOOST_SHARED_PTR_HPP_INCLUDED 当实际的(为了参数)名称是 BOOST_SHAREDPTR_INC - 你的构建是突然慢了一点。
      【解决方案4】:

      正如您在帖子中提到的,boost 代码包含大量模板代码,需要大量 CPU 周期进行编译。与此相比,多个头文件的开销非常小。

      您需要做的第一件事是找出导致编译延迟的头文件或代码行。通常不是包含头文件,而是在您自己的代码中使用其类/函数之一导致延迟。您可以通过注释掉代码片段直到编译再次快速,然后取消注释您的代码片段直到编译再次变慢来隔离负责的代码。然后你可以决定是否要用其他东西替换慢代码。您可以在这里权衡利弊或编译速度与漂亮的 boost 代码。

      您还可以做一些其他事情:

      • 清理不需要的包含语句,尤其是标题中的语句
      • 在您的头文件中,将包含替换为前向声明(如果可能)
      • 获得更快的计算机:D

      【讨论】:

      • 它似乎对我不起作用。我们已经使用了非常快的计算机,但构建过程需要几个小时......以及如何自动“找出哪个头文件或哪一行代码导致编译延迟”?代码库很大。
      • 你有这个答案的依据吗?这似乎违反直觉,简单的测试(从一个空的 main() 开始,然后从 STL 中零碎地添加包含)表明包含一个文件的成本非常实际。我错过了什么?谢谢!
      • 我不否认包含文件是有成本的。但是,根据我的经验,有时使用某些 boost 代码会产生比包含本身更大的成本。
      • 我明白了,谢谢。不过,我认为您的回答低估了包容的成本。诚然,Boost 是大量模板化的,因此实际编译代码会很耗时,但即使在非模板化代码中执行包含所需的全部内容也是一种恒定的开销。
      猜你喜欢
      • 1970-01-01
      • 2016-10-01
      • 2011-12-24
      • 2012-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多