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

编者注 :全民K歌上线1年半的从0发展到1.5亿,用户越来越多,后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,如何实现秒编至关重要。

作者:刘智勇QQ音乐社区后台开发组组长曾负责QQ空间日志、留言板等海量ugc业务和移动侧接入框架WNS的开发工作,目前负责全民K歌后台基础架构和服务的团队管理工作,拥有较丰富的海量服务、分布式架构和移动端接入经验。

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

问题背景:

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

方案思路:

参考和对比KM和网络上的一些解决方案后,考虑到现有的工程都是makefile来管理的,从改动尽可能小的角度,选择的方案是distcc+ccache,另外考虑到要尽可能减少磁盘的使用,所以把代码和ccache的ccache目录都设置到了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,并行编译就出错

目标依赖关系设置有问题,导致各个目标都并行在编译,比如有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音乐技术团队(gh_287053a877e6)

原文发表时间:2016-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CaiRui

nginx的worker_processes优化

nginx的worker_processes参数 来源: http://bbs.linuxtone.org/thread-1062-1-1.html 分享一: ...

6357
来自专栏高性能服务器开发

(八)高性能服务器架构设计总结1——以flamigo服务器代码为例

这篇文章算是对这个系列的一个系统性地总结。我们将介绍服务器的开发,并从多个方面探究如何开发一款高性能高并发的服务器程序。 所谓高性能就是服务器能流畅地处理各个客...

4396
来自专栏恰童鞋骚年

NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

  随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经显得力不从心,暴露了...

1152
来自专栏JAVA高级架构

微服务架构组件分析

服务描述:服务调用首先解决的问题就是服务如何对外描述。 常用的服务描述方式包括 RESTful API、XML 配置以及 IDL 文件三种。

1304
来自专栏CSDN技术头条

Java 程序如何正确地打日志

我们 Java 程序员在开发项目时都是依赖 Eclipse/ Idea 等开发工具的 Debug 调试功能来跟踪解决 Bug,在开发环境可以这么做,但项目发布到...

1333
来自专栏郭霖

Android Studio新功能解析,你真的了解Instant Run吗?

本篇文章首发于我的微信公众号,由于网上讲解Android Studio中Instant Run功能的文章实在是太少了,为了让更多人可以了解这个技术,我将这篇文...

2108
来自专栏腾讯大讲堂的专栏

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

编者注 全民K歌上线1年半的从0发展到1.5亿,用户越来越多,后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,如何实现秒编至关重要。...

3755
来自专栏我的小碗汤

nginx请求连接限制笔记

当时爬取时当并发过大的时候,请求就会出现卡死的情况。其实这可能就是珍爱网对请求和连接进行了限制。

1083
来自专栏Java成神之路

Java程序员常用工具集

我发现很多人没办法高效地解决问题的关键原因是不熟悉工具,不熟悉工具也还罢了,甚至还不知道怎么去找工具,这个问题就大条了。我想列下我能想到的一个Java程序员会用...

1373
来自专栏Java后端技术栈

记一次解决业务系统生产环境宕机问题!

Zabbix告警生产环境应用shutdown,通过堡垒机登入生产环境,查看应用容器进程,并发现没有该业务应用的相应进程,第一感觉进程在某些条件下被系统杀死了,然...

881

扫码关注云+社区

领取腾讯云代金券