更多腾讯海量技术文章,请关注云加社区:https://cloud.tencent.com/developer/column
作者:腾讯大讲堂
全民K歌上线1年半的从0发展到1.5亿,用户越来越多,后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,如何实现秒编至关重要。
全民K歌后台编译优化:从40分钟到30秒
问题背景
随着全民K歌功能越来越多,整个后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,严重影响了平时的开发和发布效率
方案思路
参考和对比KM和网络上的一些解决方案后,考虑到现有的工程都是makefile来管理的,从改动尽可能小的角度,选择的方案是distcc+ccache,另外考虑到要尽可能减少磁盘的使用,所以把代码和ccache的ccache目录都设置到了tmpfs上
实施过程
在五台开发机上分别安装ccache+distcc
1. 下载安装ccache
2. 安装distcc(需要先安装python)
3. 在一台主编译机器上(这里假如是192.168.1.1)mouttmpfs并做一些配置
遇到的问题
1.不并行编译ok,并行编译就出错
目标依赖关系设置有问题,导致各个目标都并行在编译,比如有comm和cgi两个目标,实际上cgi是必须在comm编译完之后才能编译的,但是在makefile里没有让cgi依赖于comm,导致在cgi目标在comm目标编译完之前就在并发执行了。解决办法:梳理依赖关系如下:
2.warning: -jN forced in submake: disabling jobserver mode
这个原因是由于递归调用的make进程里自己加了 –j选项,而不是直接使用MAKE变量,比如设置了QMAKE=make –j 10, 在子进程里直接使用$(QMAKE) –f makefile来调用就会出现此问题,解决方法也很简单,去掉QMAKE变量,直接使用$(MAKE) –f makefile就可以了
3.warning: jobserver unavailable: using -j1. Add `+' to parent make rule.原因是递归调用的makefile里面直接使用了make –f makefile这样的形式,而没有使用MAKE变量,直接修改成$(MAKE) –f makefile就可以了。深层的原因其实就是MAKE变量会把make父进程的MAKEFLAGS也带给make子进程,而直接使用make则不会传递这个变量
4.使用ccache–s观察发现有很多unsupported compiler option因为使用了-MM先生成了依赖文件.d, 而ccache不支持-MM选项。依赖文件的作用主要是在修改了某个文件后可以不用make clean 直接make, 现在编译速度这么快了,没有必要使用这个,所有都make clean 后再make就可以了,更加的安全可靠
5.使用ccache –s观察发现有很多cache miss设置CCACHE_LOGFILE环境变量,分析ccache的log发现是使用了__TIME__宏导致,修改方案有两种,一是直接去掉__TIME__, __DATE__之类的调用,二是如果不影响代码实际功能,可以在ccache.conf中设置sloppiness = time_macros
6.设置--localslots不生效,在本地永远只有4个ld进程,导致链接过程速度比较慢查阅了网上的资料,也有一些用户反馈同样的问题,反馈是distcc代码bug。网上暂时无解。看了下代码,直接修改lock.c里的默认值,重新编译,搞定!
7.编译的时候make clean all有时会失败,有时会成功,但是make clean;make all就没有问题原因是在并发的时候clean all这两个目标并发执行了,没有先make clean ,再make all,导致刚刚make出来的文件被clean掉了。目前想到的解决办法有三种:
a. 使用make clean ;make all而不是make clean all,但是在cis上好像不支持
b. 设置.NOTPARALLEL:来变成不并行,但实际测试发现全部都不能并行了。放弃。
c. 设置一个目标为clean_all,在makefile中把这个目标分成两个步骤,目前使用这个方案
8.在cis系统中willParallelExec 设置的-j默认值是4,而且不能修改,解决办法是把这个参数设置了false, 直接在下面的环境设置里设置MAKEFLAGS
9.直接使用distcc ccache g++的效果会比使用ccache g++然后再设置环境变量CCACHE_PREFIX=distcc 的效果要差。推测这里的原因是由于ccache g++是执行ccache的时候会先用本地的cache,ccahe不能使用需要编译的时候才会调用distcc, 而直接使用distcc ccache g++则会把很多原本可以在本地ccache的文件分发到其它机器去编译了
优化结果
完全没有ccache的情况下第一次编译:2分30秒左右
有ccache的情况下编译:30秒左右
超越了之前定的在1分钟之内全部编译完的目标!
后续优化
1. 工程内同名文件清理
2. 多余的include清理(include越多会导致预编译出来的文件越大,编译速度越慢)
3. 32位-》64位
参考资料
后台构建利器 ccache和distcc介绍
Linux中利用distcc和ccache加速项目编译
[转]内存文件系统使用及示例:ramdisk, ramfs, tmpfs
http://code.google.com/p/distcc/
https://ccache.samba.org/
http://stackoverflow.com/questions/8496135/parallel-makefile-require-depency-ordering
作者介绍:刘智勇 QQ音乐社区后台开发组组长。曾负责QQ空间日志、留言板等海量ugc业务和移动侧接入框架WNS的开发工作,目前负责全民K歌后台基础架构和服务的团队管理工作,拥有较丰富的海量服务、分布式架构和移动端接入经验。
领取专属 10元无门槛券
私享最新 技术干货