编译优化
编译速度一直是开发过程中的诟病,严重影响开发效率。因此提升编译速度迫在眉睫
提升编译速度的方式有:升级电脑配置 、Gradle Enterprice企业版 、Build Scan在线工具 、优化Gradle配置
升级电脑配置 、Gradle Enterprice企业版这两者简单粗暴,效果明显,但需要额外成本(money)
优化好处
- 提高开发效率
- 提升开发体验
影响因素
- 硬件性能:CPU、RAM等
- 构建配置:缓存、增量编译等
- 项目:项目复杂度和规模(代码量,模块化,依赖管理等)
- other:网速,下载慢或找不到依赖等
优化准则
- 提升复用率,代码复用及编译复用
- 减少参与编译文件,越少越快,包括代码文件、资源文件
优化方案
升级电脑配置
- 购买高配电脑
Gradle Enterprice企业版
付费,在线分析可视化工具,功能强大
Build Scan在线工具
有免费版,在线分析可视化工具,功能强大
优化Gradle配置
升级Gradle
Gradle作为一个编译工具,提升构建性能属于基本操作,每次大版本升级都会带来性能的提升,这是构建工具之外无法做到的,所以条件允许情况下第一步要升级Gradle版本(风险项:适配Gradle)
例:Gradle6.6以后对配置阶段做了提升,Gradle7.0以后对kotlin编译做了提升,Gradle8.0以后对增量编译进一步做了提升
升级Plugin
同Gradle,同步升级
gradle.properties配置
- 开启守护进程
org.gradle.daemon=true
开启后Gradle不仅可以更好的缓存构建信息,且会运行在后台,避免每次构建都先初始化再启动JVM
- 开启并行编译
org.gradle.parallel=true
Gradle默认一次执行一个Task(串行),可通过配置让其并行执行Task,从而提升构建效率,缩短构建时间
- 启用配置缓存
org.gradle.unsafe.configuration-cache=true
Gradle6.6以后新增功能,若无构建配置发生变化(例构建脚本),Gradle会直接跳过配置阶段,从而提升编译速度
- 启用构建缓存
org.gradle.caching=true
同一Task输入不变时,Gradle会直接检索缓存输出,不用再次执行该Task,从而提升编译速度
- 使用非传递R类
android.nonTransitiveRClass=true
非传递R类,Gradle插件8.0.0及之后版本默认开启。开启后,module中定义的资源不会在依赖该module的模块R.class中生成引用。引用module资源时需全路径引入
- JVM配置
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8 -XX:+UseParallelGC
- 根据自身电脑配置,通过jvmargs调整内存堆大小
- 使用JVM并行垃圾回收器-XX:+UseParallelGC
- 停用Jetifier标志
android.enableJetifier=false
Jetifier是把support转为AndroidX的工具,当前基本都已适配AndroidX,可关闭,从而提高性能
- 启用K2
kotlin.experimental.tryK2=true
kotlin 1.9.20中K2已是beta版本,可开启使用
使用KSP代替kapt
kapt是kotlin注解处理器,运行速度明显慢于Kotlin Symbol Processor(KSP)
- project -> build.gradle.kts
bash
plugins {
id("com.android.application") version "8.2.1" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
id("com.android.library") version "8.2.1" apply false
// 启用KSP,与kotlin版本需对应
id("com.google.devtools.ksp") version "1.9.22-1.0.16" apply false
}
- module -> build.gradle.kts
scss
// 导入plugin_version依赖类
import com.dcxing.plugin.version.*
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
// 导入plugin_version插件
id("com.dcxing.plugin.version")
// 启用KSP
id("com.google.devtools.ksp")
}
android {
...
}
dependencies {
implementation(Lib.core_ktx)
implementation(Lib.appcompat)
// KSP注解处理比kapt更快"androidx.room:room-compiler:2.5.0"
ksp(Lib.room_compiler)
...
}
启用增量编译
Gradle4.10及以后默认开启,以下版本手动开启
ini
// build.gradle文件添加
...
tasks.withType(JavaCompile).configureEach {
options.incremental = true
}
...
升级Java
Gradle运行在Java虚拟机(JVM)上,Java性能提升也有利于Gradle的编译
调整AS运行内存
-
在AS底部工具栏右键勾选Memory Indicator可查看内存信息
-
AS安装目录 -> bin -> studio64.exe.vmoptions
-Xms256m:初识堆内存
-Xmx2048m:最小堆内存,可改为-Xmx4096m
依赖关系优化
- 删除无用依赖
- 优化存储库顺序
scss
/**
* Gradle解析时,默认按配置中声明的仓库地址顺序检索,为减少检索时间,合理调整依赖仓顺序
* google() > mavenCentral() > other
*/
repositories {
google()
mavenCentral()
maven { setUrl("https://jitpack.io") }
...
}
- 优化依赖下载顺序
ruby
/**
* 未翻墙情况下,使用镜像地址提升下载速度
*/
repositories {
// 阿里云https://juejin.cn/post/6907479665305190408
maven { url 'https://maven.aliyun.com/repository/public/' }
google()
mavenCentral()
maven { setUrl("https://jitpack.io") }
...
}
- 依赖版本优化 使用具体版本,避免使用动态版本(2.+)或快照版本(2-SNAPSHOT),避免构建时检索新版本(默认24h检索一次)
arduino
// 可使用如下方法配置build.gradle
configurations.all {
// 动态版本缓存时效
resolutionStrategy.cacheDynamicVersionsFor(60, "minutes")
// 快照版本缓存时效
resolutionStrategy.cacheChangingModulesFor(12, "hours")
}
资源过滤
dev版本,过滤暂时不需要的资源(例语言资源、屏幕密度资源),指定一个即可
csharp
// build.gradle.kts
android {
flavorDimensions.add("app")
productFlavors {
create("dev") {
dimension = "app"
// 指定资源
resourceConfigurations.add("en")
resourceConfigurations.add("xxhdpi")
}
...
}
}
按需编译
- 按需编译版本:debug、release
- 按需依赖插件:debug、release
过滤禁用Task
rust
// build.gradle.kts
android {
...
gradle.taskGraph.whenReady {
tasks.forEach { task ->
if (task.name.contains("dev")) {
// 禁用名称包含dev的task
task.enabled = false
}
}
}
}
资源优化
- 图片转为Webp格式或使用svg矢量图
- 选中图片 -> 右键 -> Convert to WebP...
webp是一种支持有损压缩、透明度的图片格式,比jpg、png有更好的压缩效果
- 停用png处理
arduino
// 不需要对res/drawable/下图片进行无损压缩时使用
android {
buildTypes {
release {
// 构建时停用自动png压缩,提高编译速度
isCrunchPngs = false
...
}
}
}
移除动态配置项
- apk文件名添加构建时间,每次编译都会更新影响编译速度
- 动态的versionName、versionCode,每次编译都会更新影响编译速度
离线Gradle
AS -> Settings -> Build,Execution,Deployment -> Build Tools -> Gradle
模块化设计
通过aar依赖,减少参与编译代码,从而提高构建速度
使用构建分析工具
- Build Analyzer:AS自带,相对基础
- Profile:本地分析,相对基础
- Build Scan:在线分析工具,功能强大
- Enterprice:付费