最近在一次技术分享中,有网友问我小公司可以考虑做哪些编译优化?我觉得这个课题也还是挺有必要展开下讲讲的。
编译优化方面其实我个人觉得并不一定是特别高大上的东西,除了一些特别深水区的地方,还是有些东西还是能从细微处进行展开的。今天我们就尝试下拉他下水。
组件化
组件化和编译优化有啥关系? 有些人甚至觉得可能会拖慢整个工程编译速度吧。
在我的认知中gradle
是一个并行编译的模式,所以当我们的工程的taskGraph
确定之后,很多没有依赖关系的模块是可以并行编译的。这样的情况下我们就可以充分的使用并行编译的能力。
而且从另外一个角度gradle build cache
出发,我们可以拥有更细致的buildcache
。如果当前模块没有变更,那么在增量过程中也可以变得更快。
巧用DI或者SPI
以前我其实挺反感DI(依赖注入)
的,我认为会大大的增加工程的复杂度。毕竟掌握一门DI(依赖注入)
还是挺麻烦的。
但是最近我突然想通了,我之前看GE(Gradle Enterprise)
的时候,发现有些业务模块之间有依赖关系,导致了这些模块的编译顺序必须在相对靠后的一个状态,但是因为com.android.application
会依赖所有业务模块,这个时候就会触发水桶理论,该模块的编译就是整个水桶最短的短板。也让整个工程的并行编译有一段时间不可用。
那么这种问题我们可以通过DI(依赖注入)
或者SPI(服务发现)
的形式进行解决。模块并不直接依赖业务的实现而是依赖于业务的一个抽象接口进行编程,这样可以优化既有工程模块间的依赖关系。
道理虽然简单,但是真的去抽象也会考验对应开发的代码能力。
关注AGP优化方案
这部分我觉得是很容易被开发遗忘的,比如我们最近在做的buildConfig,AIDL编译时默认关闭,还有去年到今年一直在进行的非传递R文件的改造。官方的Configuration Cache,还有后续的全局AGP通用属性,还有默认关闭Jetfied等等,这些跟随AGP迭代的属性。
结果上看关闭非必要模块的buildConfig AIDL可以让全量编译时间缩短大概2min,当然主要是我们模块多。而非传递R可以让我们的工程的R文件变更的增量缓存更好管理。
Kotlin技术栈更新
kt
已经发布很长时间了,最近最让我期待的是kt2.0带来的K2的release版本。能大大的提升kotlin compiler编译速度。
另外还有kt之前发布的ksp,是一个非常牛逼的kapt的替代方案。而且官方也在逐步对ksp进行支持。比如room这个框架就已经适配好了ksp。我自己也写过好几个ksp插件。我个人认为还是非常酷的。
最后还有一些废弃东西的下架,比如KAE(kotlin-android-extensions)
这种已经被明确说是后续不继续进行支持的框架。我们最近尝试的方案是通过Android Lint
把所有声明KAE
的进行报错处理。剩下的就是业务自行决定是改成findViewById
还是viewBinding
。
花点钱接个GE
如果这个老板不太差这么点钱,我真的觉得GE(Gradle Enterprise)
是个非常好的选择。可以很直观的看出一些工程的编译问题,而且对接的gradle同学也都很专业。
不要轻易魔改Gradle
非必要的情况下,个人是不太建议同学们改这个的。非常容易破坏整个编译缓存系统!这里不仅仅只针对Transform
,还有对任意编译产物进行修改的,比如xml
,资源等等。当然如果可以的话,尽可能的使用最新AGP
提供的一些新的api去进行修改吧。这个可以多参考下2BAB
大神的一些文章。
另外比如很多非必要的Transform转化建议本地编译的时候就直接关闭了,虽然可能会出现一些本地行为不一致的情况,但是可以大大的优化一些编译速度。字节码不是炫技的工具,谨记!
总结
最近基本没有做一些特别适合分享的内容,文章也就没有更新了。各位大佬们体谅啊,抱拳了。
在下封于修,前来讨教。既分生死,也决高下。