android app性能优化

Android构建加速--增量编译

2022-11-07  本文已影响0人  获取失败
背景

abooster是20年的时候我给hago弄的构建加速插件,当时由于hago是海外项目,需要上架GP的,因此不能像国内那样搞插件化,加上hago整个项目的规模也十分之庞大,几十个modules几十上百万行代码,并且常年不更新agp kgp,所以hago的构建是比较慢的,如果动到一些底层base库那个编译等待时间真的是要命。为了解决编译耗时问题,所以开始着手研究agp跟kgp,开发构建加速插件。不过由于某种原因,这个插件项目刚开发完还没来得及测试就被我弃用了。直到今年有同事希望我能把资源编译也加上,研究下发现也是可行的,功能加上后整理了代码跟资料后,现把项目开源出去,供同样受编译耗时问题困扰的友人们参考参考。

源码地址

使用介绍

abooster并不是通用的解决方案,要根据自身的项目环境去适配,目前已经适配的agp版本是3.4.2 已适配的kgp版本是1.4.32 (版本是比较低,因为公司的项目还在用 没办法。。)

abooster的使用比较简单,只需要在项目根build.gradle下apply下plugin就可以了,如下:

dependencies {
      classpath "com.android.tools.build:gradle:${gradle_version}"
      classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
      classpath "com.yy.sdk.abooster:plugin:2.0.0-SNAPSHOT"
}
apply plugin: 'com.yy.sdk.abooster.plugin'

使用的时候你可以正常通过assembleDebug(或as里的run三角icon)来跑你的代码,abooster拦截了gradle的构建流程,会自动检测是否支持增量,能支持增量编译的话会走abooster内部构建,不支持增量编译会自动跑回系统的默认构建流程(开源版暂不提供此功能)。又或者是手动执行abooster的buildDebugBoosterBundle任务,buildDebugBoosterBundle任务会触发kotlin java等代码的编译,或资源的编译打包等等。需要注意的是,只有App模块才会有buildDebugBoosterBundle,Android Library模块是没有的,使用的时候也只管跑App模块的任务就可以了,其余模块下的abooster任务可以不管。

abooster只支持增量构建并不支持全量构建,因此第一次执行buildDebugBoosterBundle任务的时候所有task状态都会是incremental:false,false的时候abooster默认是不执行构建的并且会清理掉缓存目录,第二次跑buildDebugBoosterBundle的时候才会是增量,这个其实也很好理解,增量毕竟是在上一次的基础上diff出来的,所以第一次必然是非增量的。

abooster目前并不支持java library模块或gradle-plugin模块,不支持的模块可以配置ABoosterExtension来进行exclude 譬如:

ABooster {
    pkg = "com.yy.sdk.abooster"
    launchActivity = ".MainActivity"
    exclude = ['testlib']
}

并不是遇到了什么技术难点所以不支持,仅仅是因为我没时间去做适配而已。。。
pkg launchActivity是可选配置,不配也没关系,我会通过解析AndroidManifest.xml把默认配置读取出来。

原理介绍

abooster能把原来一分钟甚至是几分钟的构建时长缩短到10秒内(当时在hago上面测到的数据是,五六分钟的构建时间可以缩短为8-10秒),因为abooser的构建是full-incremental,假设你的项目里有上百个类,但是你只修改了a.java b.kt以及test_activity.xml,abooster只会编译这几个修改文件,所以构建速度是很快的,其实agp kgp本身也是支持增量构建的,但官方的编译工具首要核心要求是要稳定,BUG少且能满足各种不同场景下的构建,因此构建流程会很重且很复杂,最终就是总的编译耗时长。

abooster的原理比较简单,跟热修复类似的,先会把修改代码打成补丁包,接着push到手机上,installer会解析并且安装这个补丁包。补丁加载逻辑是从tinker拷过来修改的,这里要感谢下微信团队开源出来的这么优秀的项目以及相关的干货技术文章。

abooster的编译构建逻辑是参考了agp kgp源码后重写出来的,这块有两个核心重点,第一个是修改文件检测 第二个才是编译打包

源码介绍

abooster核心的modules有两个installer plugin,前者负责补丁包的安装,后者是补丁包的打包插件,这里只介绍构建插件。

./gradlew :app::buildDebugBoosterBundle -Dorg.gradle.daemon=false -Dorg.gradle.debug=true --info

然后在as上面起个远程配置挂载上去就可以了,之后就跟调试普通代码一样了,下断点单步执行。

写在最后

daemon原生构建就支持了依赖检测的,譬如a方法被修改了,b引用了a,那么b也会被带进去重新编译,但是实践过程中发现一个很奇怪的现象,kotlin间接引用Java时会报类似这样的错误

Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class com.yy.sdk.abooster.Test, unresolved supertypes: com.yy.sdk.abooster.JavaTest

如果把编译输出指向kotlin原来的kotlin-classes目录就不会报错,放其他任意目录都会报错,没搞懂这个问题的原因,但是我又不想把abooster构建出来的产物放在kotlin-classes里,因为这样必然会影响到了compileDebugKotlin任务的增量检测,时间关系我只能先把这个依赖检测编译功能给砍了。
abooster目前也不支持multi variant,要实现multi variant还得实现一套variant data variant manager等等,目前只支持没有配置过flavor的项目,且只有debug环境下才支持(release没有支持的必要)。代码写得比较渣,凑合着来看吧,毕竟从开始研究到落地也仅仅给了几个周末的时间而已,源码只提供一种思路,一种方案跟实现。

上一篇 下一篇

猜你喜欢

热点阅读