一、概述
经过多年的发展,美柚iOS项目代码已经达到40W行+的规模,所使用的 Pod 库的数量达到了110+,App Store 安装包210M+,在这么大的项目规模下(CI机器 MAC配置:3 GHz 8-Core Intel Xeon E5;时间:发布20min+),(开发机器iMac :Retina 5K, 27-inch, 2017 融合硬盘;时间:build30min+)打包、编译问题逐步成为我们团队一个躲不过的痛,严重影响了我们的研发效率与其他团队之间的协作。
我们一台13年的ci机器同时需要承接七八个项目、多个分支的打包任务,在有多个项目同时打包的情况,显得尤其地力不从心。
在硬件资源有限的情况下,并且在无侵入、无影响现有的业务的前提下,如何解决这些摆在团队面前的难题,便成了我们迫在眉睫的迫切需求,最近半年多来一直在寻找加快打包速度的方案。
二、编译提速探索与尝试
1、CCache
CCache 是一个编译缓存器,一个能够把编译的中间产物缓存起来的工具
其原理是通过把项目的源文件用ccache编译器编译,然后缓存编译生成的信息,从而在下一次编译时,利用这个缓存加快编译的速度,目前支持的语言有:C、C++、Objective-C、Objective-C++
下面这张图基本就阐述了CCache的工作原理。
在项目中的实际编译流程
Ccache我们经过在工程的一番尝试、确实在某些方面上极大的提升了我们出包的速度。美柚iOS Ci打包从之前的最快20min+出包到最快10min,确实能够给我们带来比较不错的提升,大大加快了我们项目的出包速度。在我们项目运行了几个月后,对于我们项目的情况,也发现了一些问题,现在总结了以下几点:
优点:
对我们项目中有存在些问题点:
2、静态库二进制方案的探索
虽然我们已经在Ci的在应用了Ccache已经有提升近一倍的出包速度了,但是存在的问题也比较明显。
在去年的某次技术周会上,我们的大佬提出了使用二进制编译的自研任务,可以更进一步提高研发效率。得到了大佬的启发后,就一直在实践与探索二进制之路上。
我们的项目使用 CocoaPods 来管理第三方库和私有库的依赖,对大部分项目来说应该是标配了。目前还是纯 Objective-C 的项目,有少量C++,暂没有引入 Swift。
3、 调研过的二进制组件方案
下面列出研究过的一些主流方案以及最后没有采用的原因,这些方案有各自的局限性,但是也给了我不少启发,思考过程跟最终方案一样有价值。
3.1、Carthage
Carthage可以将一部分不常变的库打包成framework,再引如到主工程,这样可以减少开发过程中的编译时间。Carthage 可以比较方便地调试源码。因为我们目前已经大规模使用 CocoaPods,转用 Carthage 来做包管理需要做大量的转换工作,变动太大,不满足我们的无侵入、无影响现有的业务,所以不考虑这个方案了。
3.2、cocoapods-packager
cocoapods-packager 可以将任意的 pod 打包成 Static Library,省去重复编译的时间,一定程度上可以加快编译时间,但是也有自身的问题:
3.3、cocoapods-binary
Cocoapods-Binary(Cocoapods 官方推荐的二进制插件), 是一个即时生成二进制包并缓存,而非像 CocoaPods-Packager 仅仅针对单个私有库的。原理是通过 CocoaPods 提供的 pre_install hook 在 pod install 的 prepare 阶段拦截到当前的 pod install context,进而 fork 出一份独立的 installer 以完成将预编译源码 clone 至 Pod/_Prebuild 目录下,同时也存在几个不足之处:
3.4、cocoapods-bin 双私有源
该插件进行二进制化的策略是采用双私有源,即2个源地址,一个静态服务器保存预先打好包的framework,一个是我们现在保存源码的服务地址,在install的时候去选择使用下载那个,是个很不错的项目,深受启发。
优点:
对于在我们项目中存在的不足之处:
4、 思考与总结
经过一个多月来对业界存在的轮子的分析和思考,并在一定的实践后,最后我们决定自己造一个灵活的、可配置的、简便的、无入侵的、双私有源二进制组件辅助插件。
接下来就撸起袖子,努力干吧~,骚年
三、双私有源二进制组件简介
在受到cocoapod-bin启发后,在借鉴它的部分框架下,我们实现了自己的二进制辅助插件cocoapods-imy-bin,并新增了几个命令和二进制源码调试能力。
1、能做什么?只要能编译通过,就制作
在cocoapods-imy-bin的辅助下,能无侵入式自动化地制作所有符合条件的组件为二进制,且对于频繁的业务组件也能轻松的应用上二进制组件,无需多余操作,一切交给cocoapods-imy-bin自动化运行。
同时对于研发人员,也能提供独立的二进制组件给研发人员使用,解决日常的编译 效率、跑真机效率低下,被墙等各种问题。
我们的口号是: 只要能编译通过,就制作。 一次编译到处使用,无入侵。
即使独立的组件库编译不通过,整体项目能编译通过也制作。
整套环境下来,没有让我们的开发人员改变原来的开发习惯,没有改动业务中相关的代码,基本上做到了使用人员无感知状态。
2、Ci打包效果
2.1 单项目 - 编译最快2分钟一次
上图是个由我们打了几千个包的经验得出对单个项目编译时间大致的曲线图。这里假设一台机器只一次只有一次job。Y轴编译时间,X轴某次的编译, 红色线条表示的是原生(未使用Ccache和二进制组件),黄色线表示使用了Ccache,蓝色表示使用了二进制组件。
由图可以看出来在无任何辅助下原生的编译时间曲线(红色)是趋于平缓,在20min上下左右。Ccache和二进制第一次在无任何缓存的情况下,在一定程度上是会比原生的耗时,Ccache主要耗时在边编译边缓存项目的编译产物。二进制主要耗时在编译完成后,对.a编译产物的组装和push到私有源仓库的时间上(这个跟所采用有关系,如果没有利用Jenkins 编译后的产物制作二进制就不存在。)。
在ccache完全命中、二进制文件完全都存在的情况下,ccache比原生的提高一倍以上, 二进制会比ccache编译时间再提高一倍,且稳定在2分钟左右。二进制在之后的表现更趋于平稳,而ccache在修改了某个被引用较多的文件时、如底层的公共文件后,命中率就会大大地降低,有时会比不用ccache更耗时,如#4位置。在ci有多个job同时并发在跑的情况下,由于ccache 需要对IO频繁地读写操作,耗时表现可能会更糟糕些,我们经常遇到过等了七十几分钟才出包的情况。
二进制的编译时间相对平稳很多(蓝色曲线),在我们架构强有力的支撑下,划分出110多个独立组件,每次的打包基本上是就耗在某个组件的编译+archive。如果是某些变更比较频繁的组件,我们还可以考虑对颗粒较大组件配上ccache,做双层编译缓存。双层编译缓存原理是Pods组件库无二进制组件采用源码编译时,源码编译同时应用ccache缓存支持,加速源码组件的编译。
同时组件库可以配合Gitlab-Ci的runner的应用,每次已提交代码就触发独立组件的制作二进制,让每次的编译速度都达到最快,蓝色二进制曲线将会更接近直线。Gitlab-Ci具体的使用教程参见后文。
如果存在有独立组件无法编译问题和版本依赖问题,也可以再跑个定时Job,或者其他轮询条件Job,及时提供最新二进制组件。
2.2、多项目情况
一台机器上多个项目的ccache显得是比较吃力的,且不稳定,超出ccache的缓存最大值就会被清掉。
使用了二进制后,即使是多个项目编译时间都是趋于比较平稳的。这里面的原理估计大家都能想得到为什么。
3、开发使用效果 - 10倍以上的提升
在Podfile引入插件后,在pod install/update后,符合条件的情况下,会自动转换为二进制组件。
在我们的开发机器(iMac :Retina 5K, 27-inch, 2017 融合硬盘;)上,全量代码之前Build需要30min+,现在使用全部使用二进制后,编译最快只需要2min+就可以,提高的效率达到10倍以上。
当您在使用独立组件库编译开发的时候,其实不妨试试这个二进制的方案去跑整个项目,说不定二进制的方案比独立组件库跑起来还迅速。
3.1.源码编译
Ps:110+个Pods库中,有20+个稳定Pods库已经被制作为二进制库,并非全部源码编译,如何全部转换为源码编译,实际数字会比这多出很多。
3.2. 二进制编译 - 全量最快2分钟
Ps:有2个Pods和5个Action Extension使用源码编译,其他全部是二进制Pods。
在二进制Build 127秒中(arm64和armv7),除了源码编译的时间外,约45秒消耗在copy pods Resource。
实际在编译模拟器x86_64架构时只需要90秒不到的时间。
全量编译中,13496个Tasks/727个Tasks,1710秒(28.5分钟)/127秒(2分钟),编译速度提升的速度远远超过10倍。
3.3 演示
在环境搭建完后,开发人员在Podfile中,加入以下两句,就能享用到自动切换为二进制组件,体验极速编译。
- plugin 'cocoapods-imy-bin'
- use_binaries!
4、功能点
目前cocoapods-imy-bin插件支持的功能如下
近日三大运营商先后发布了2020年经营报告。整体行业发展状况有所好转,至少无论...
人工智能技术正在深入到工作环境中,不仅取代了平凡和重复的人工工作,而且还以...
不管在任何领域,手续费本来都是一种正常的收费名目,但如果在近乎垄断的领域,...
目前,国内政策主要围绕着5G的建设和应用展开。工信部发布了《基础电子元器件产...
1.我有一万种想见你的理由,却少了一种能见你的身份。 2.我想谈一场公开的恋情...
对于希望在家远程工作并保持高生产率的工作团队来说,人工智能可以起到重要的作...
近日,南极首次发现一只金黄色企鹅,这只被戏称是充了黄钻的企鹅摇身一变成为网...
上周微信刚刚更新了8.0版本,带来新的表情、状态、音乐MV等玩法,直到现在关于它...
在这样技术先进的世界中,诸如检查之类的关键工业流程仍然效率低下,成本高昂,...
牛年马上来,彩蛋已先到。中国市场强劲的购买力帮苹果创造了新的 iPhone 销售历...