zoukankan      html  css  js  c++  java
  • 如何加速C++文件的编译速度?

    一、为什么慢?

    重要的一个原因是C++的基本 头文件-源文件的编译模型:

    • 每个源文件为一个编译单元
      • 头文件数量多,可能会包含上百甚至上千个头文件
      • 存在重复解析,每个编译单元中,这些头文件都要从硬盘里读取然后被解析
    • 每个编译单元都会产生一个obj文件
      • 这些obj文件被link到一起,此过程很难做到并行

    二、如果加快编译?

    1. 代码角度

    1.1 使用前置声明

    不要直接包含头文件,推荐使用前置声明。

    前置声明只是在代码中引入了类Foo,是一个不完全类型——因为我们不知道它具体包含了哪些成员。

    不完全类型只能在非常有限的情况下使用:

    • 只能定义指向这种不完全类型的指针和引用(因为不知道多大?)
    • 只能声明(但不可以定义)以不完全类型作为参数或者返回类型的函数(也是因为不知道多大?)

    原因:

    • 任何一个多余的头文件,都可能会被无限放大。
    • 虽然很多时候前置声明某个namespace中的类比较痛苦,但你仍值得这么做
    • 类的成员、函数参数等尽量使用引用、指针,为前置声明创造条件

    坏处:

    • 隐藏了依赖关系,头文件改动时,用户代码会跳过必要的重编过程
    • 前置声明可能会被库的后续更改破坏
    • 前置声明来自命名空间std::的symbol时,其行为是未定义的

    使用原则:

    • 尽量避免前置声明那些定义在其他项目中的实体
    • 函数:总是使用#include
    • 类模板:优先使用#include

    1.2 使用Pimpl模式

    全称 Private Implemention

    原因:

    • 传统的C++类接口与实现是放在一起的;Pimpl可实现二者完全分离
    • 只要公共接口不变,对类实现的修改,始终只需要编译此CPP,不涉及头文件的重编
    • 此外,对外界提供的头文件内容也会精简很多

    1.3 高度模块化

    尽量低耦合,尽可能减少相互依赖。

    原因:

    • 文件与文件之间,一个文件的变化,尽量不要引起其他文件的重编
    • 工程与工程之间,一个工程的修改,尽量不要引起其他工程的编译
    • 要求头文件内容尽量单一,保证内聚性
    • 优化思路:可以把代码中最hot的头文件找出来,拆分成高内聚的独立小文件

    1.4 删除冗余的头文件

    项目大了,又涉及团队协作,很有必要通过自动化脚本识别和删除冗余的头文件包含

    1.5 注意inline和template

    这两种机制都会强制我们在头文件中包含实现,会增加头文件的内容。在使用这两个新特性之前,需要仔细权衡一下。

    2. 综合技巧

    2.1 预编头文件(PCH)

    **把一些常用的、但不常改动的头文件放到预编译头文件中。 **

    好处:在单个工程中,就不需要在每个编译单元里一遍又一遍的load与解析

    2. 2 Unity Build

    考虑将所有的CPP包含在一个CPP中(如all.cpp),然后只编译all.cpp

    好处:只存在一个编译单元,不会重复的load与解析,同时只产生一个obj,链接时也不需要密集的磁盘操作。

    2.3 ccache

    全称 compiler cache,借助上一次编译的结果,使rebuild在保持结果相同的情况下,极大地提高速度。

    好处:ccache是根据文件内容为判断原则,而非更新时间(git clone时不可靠)

    2.4 避免过多的Additional Include Directories

    编译器在定位include的头文件时,是根据你提供的include directories进行搜索。如果提供的目录过多,则在搜索定位时耗费的时间就会增加。

    3. 编译资源

    3.1 并行编译

    通过 make -j4开启4线程并行编译。

    3.2 升级磁盘

    编译速度比较依赖磁盘的读写性能,在多线程并行编译时,磁盘性能可能存在瓶颈,可以升级更高转数、或者SSD、或者RAID0

    3.3 分布式编译

    利用多态机器同时编译,通常在比较大的工程上使用

  • 相关阅读:
    zookeeperclient代码解读
    封装scrollView 循环滚动,tableViewCell(连载) mvc
    PHP经典项目案例-(一)博客管理系统5
    Android插件化(三)载入插件apk中的Resource资源
    比树莓派配置好接地气的香蕉派上手初体验
    HDU Group
    JVM 类的卸载
    JVM 自定义类加载器
    JVM 初始化阶段例子
    JVM 初始化阶段例子 final常量
  • 原文地址:https://www.cnblogs.com/CocoML/p/14643379.html
Copyright © 2011-2022 走看看