C++项目要怎么缩短编译时间?
C++项目要怎么缩短编译时间? 对于像OceanBase这样的大型c++项目来说,降低编译时间是不得不为之的基础性工作。否则,调试迭代,准入测试,持续集成,编译无处不在,看着屏幕等待时光流失的感觉可不好。目前,我们通过探索采用以下一些方法。
1. 采用distcc进行分布式编译
2. 大型distcc肉鸡场,机器宕机时有发生,distcc经常会卡死。而且肉鸡上其他大负载的程序往往会受编译任务的影响,招致肉鸡贡献者的抗议,甚至威胁要收回肉鸡!(收回就收回呗,禁止你的ob-make权限,以后自己玩儿去)
3. 为了解决上面问题,引入dmucs做distcc肉鸡的故障检测和自动负载均衡管理。它通过安装在各台肉鸡上的agent收集机器负载,动态分发编译任务。
4. 改用上述方案后,每次编译都会和dmucs master进行一次通讯。这个单点高可用又成了问题。采用简单粗暴的办法解决:
1)dmucs master进程定时健康监控和自动重启。修复dmucs master实现中的bug。
2)修改dmucs客户端gethost添加重试逻辑
3)使用我封装的ob-make代替make,在检测到dmucs故障的时候,退化为本地编译。这样让短暂的服务不可用对开发的影响变小。
5. 减少编译时不必要的依赖
1)头文件中,能使用前置声明的,就不使用include。非常重要!(见评论中补充)
2)使用一个Makefile代替原来的嵌套Makefile。后者会影响编译依赖的正确分析。
6. 减少链接时间。distcc只能把编译阶段并发,链接还是在本机。链接的耗时主要是因io密集。
1)为此,在本机开辟一个内存文件系统(tmpfs)或者多盘做RAID0,优化io。
2)distcc预处理的临时文件也放到这里。
3)此外,采用高版本的linker(golden ld?)也能提升链接速度,不过由于维护的原因没有采用
7. 本地开发迭代期间,采用debug模式编译选项,这个选项下关闭不必要的影响编译时间的选项。
关于ccache,我们也尝试使用过,不过效果一般。
1)日常开发迭代中make clean后从头编译的情况很少
2)如果这种情况频繁,可能你的makefile写的有问题
————
补充下最新进展。
最近,随着持续集成扩容等对分布式编译的压力增大,dmucs master节点服务gethost请求获取编译机器的能力变成了瓶颈(dmucs是单进程模型性能较差),我们把dmucs master也做成了多节点。ob-make随机选择一个节点作为主master,以均衡负载。修改gethost,编译过程中如果主宕机,会自动重连其他节点,以提升可用性。新增负载监控。默认并发度-j84,哈哈。 “目前的编译方法是把每个CPP文件都编译成.o文件,然后再把这些.o文件连接起来”难道这不是F5默认的方法吗,你还有别的办法?你还可以给你引用的库做precompiled header,你还可以把你的硬盘换成SSD。如果你频繁git push origin master的话,你可以把盘坐在内存里,不需要本地留一个repo了。 精简头文件,让cpp文件看到尽量少的东西。 才4-5000行也能编译这么久,不知道用了多少模版呢。。。
跟你说个事儿(估计很多人不知道),gcc 也可以用预编译头文件。 试下把需要实例化的类在预编译头文件里typedef一下,让预编译结果包含一波模版实例化(第一阶段查找)结果,不知道会不会对你的问题有帮助。 搭一个 distcc 集群,配合 ccache,会显著的提高速度。(记得配ssd!)
头文件也有很大优化空间,可以做,但是比较麻烦。还是 distcc 这种可扩展方案比较好。
尽可能用新版本的编译器,尽可能关闭优化项。(只是调试的时候关闭,release的时候肯定是要按照需要打开)
还有就是模版是非常消耗编译时间的。尽管我觉得没必要因为编译慢而放弃使用模版。 vs有个插件,可以做联合编译。同发局域网内的电脑 都能参与进来。然后会快很多,原来编译一次半小时,联合一下几分钟搞定。
再结合楼上说的增量编译,基本能做到在可接受范围内吧。编译的时候去尿一泡回来一般就好了。
插件名叫:incredbuild,是收费的。当年我用的是盗版的。 不要在.h里做不该做的事情 make -j + ccache+distcc,基本可以保证make的时候最大程度增加并发度。前提是makefile依赖写对。对于特别大的项目,把output目录放在tmpfs里面,windows下放到ramdisk里。缺点是断电就没了,所以及时生成package.
物理设备提升,内核硬盘这些。
联合编译
多线程编译-j8