全民 K 歌后台编译优化:从 40 分钟到 30 秒

2,327 阅读5分钟
原文链接: mp.weixin.qq.com

全民K歌后台编译优化:从40分钟到30

问题背景:

随着全民K歌功能越来越多,整个后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,严重影响了平时的开发和发布效率

方案思路:

参考和对比KM和网络上的一些解决方案后,考虑到现有的工程都是makefile来管理的,从改动尽可能小的角度,选择的方案是distcc+ccache,另外考虑到要尽可能减少磁盘的使用,所以把代码和ccacheccache目录都设置到了tmpfs

实施过程:

在五台开发机上分别安装ccache+distcc

1.下载安装ccache


#!/bin/sh

tar -xvf ccache-3.2.4.tar.gz

cd ccache-3.2.4

./configure && make && make install

cd /usr/local/bin

ln -s ccache /usr/local/bin/gcc

ln -s ccache /usr/local/bin/g++

2.安装distcc(需要先安装python

#!/bin/sh

[ -d distcc-distcc-3.1 ] || unzip distcc-distcc-3.1.zip

cd distcc-distcc-3.1/

./autogen.sh

./configure&&make&&make install

#启动:

distccd --daemon -a 192.168.1.1 -a 192.168.1.2 -a 192.168.1.3 -a192.168.1.4 -a 192.168.1.5

3.在一台主编译机器上(这里假如是192.168.1.1)mouttmpfs并做一些配置

#mount tmpfs

mkdir–p /data/home/user_00/AutoBuild

mount tmpfs /data/home/user_00/AutoBuild -t tmpfs -o size=10g

 

#设置环境变量,可以直接设置到运行用户的.profile中

export DISTCC_HOSTS="localhost/16 --localslots=12 192.168.1.2/5192.168.1.3/5 192.168.1.4/5 192.168.1.5/5"

export CCACHE_PREFIX=distcc

export MAKEFLAGS="-j28"

 

#设置ccache的cache目录到tmpfs

echo “cache_dir = /data/home/user_00/AutoBuild/.ccache”>>/data/home/user_00/.ccache/ccache.conf

遇到的问题:

1.不并行编译ok,并行编译就出错

目标依赖关系设置有问题,导致各个目标都并行在编译,比如有commcgi两个目标,实际上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环境变量,分析ccachelog发现是使用了__TIME__宏导致,修改方案有两种,一是直接去掉__TIME__, __DATE__之类的调用,二是如果不影响代码实际功能,可以在ccache.conf中设置sloppiness = time_macros

6.设置--localslots不生效,在本地永远只有4ld进程,导致链接过程速度比较慢

查阅了网上的资料,也有一些用户反馈同样的问题,反馈是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的情况下第一次编译:230秒左右


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