第4章:Baseline Profile的生成与集成
Baseline Profile 是 Android 编译优化中的关键手段,它通过预编译热点路径并固化到 APK 中,使 Compose 组合函数在首次启动时直接以 AOT 二进制执行,大幅降低初始组合耗时。本章覆盖从手工编写到自动生成、从编译配置到运行时安装的完整流程,帮助你将 Baseline Profile 集成到 Compose 项目中。
4.1 手工生成 baseline-prof.txt
手工生成适用于已掌握性能瓶颈的场景。文件位于 src/main/baseline-prof.txt,每行对应一条 规则,格式为:pattern
其中 pattern 使用简化的字节码规则匹配方法、类或调用链。
HSPL/HSPLs:匹配相同签名层次结构的方法。!:取反,排除某些路径。*:通配符,匹配任意方法/类名。**:匹配任意子包或嵌套类。
示例:为 Compose 初始组合热点生成 profile
HSPL com.example.app.MainActivity.onCreate
HSPL androidx.compose.runtime.ComposerImpl.composeContent
HSPL androidx.compose.ui.layout.LayoutNodeSubcomposeLayoutState.subcompose
HSPL androidx.compose.foundation.text.BasicTextKt.BasicText
HSPL androidx.compose.material3.ButtonKt.Button
!HSPL androidx.compose.runtime.snapshots.Snapshot.current
规则会指导 ART 在安装时预编译这些方法的 AOT 代码。避免添加过多规则(建议 500 条以内),否则预编译耗时增加、APK 体积膨胀。
adb shell pm art profiler --dump-baseline <package> 查看实际被编译的 baseline 方法。
4.2 使用 Macrobenchmark 自动生成
Macrobenchmark 库提供 BaselineProfileRule,在真机上运行一个“冷启动”场景,自动收集首次组合的热点方法并输出 profile 文件。推荐 Compose 项目使用此方式保证覆盖全面。
4.2.1 添加 Macrobenchmark 模块
在项目中创建 :macrobenchmark 模块(通常为 Android Library),并添加依赖:
// macrobenchmark/build.gradle.kts
plugins {
id("com.android.test")
id("kotlin-android")
}
android {
namespace = "com.example.app.macrobenchmark"
targetProjectPath = ":app"
...
}
dependencies {
implementation("androidx.benchmark:benchmark-macro:1.2.3")
implementation("androidx.test.ext:junit:1.1.5")
implementation("androidx.test.espresso:espresso-core:3.5.1")
}
4.2.2 编写 Baseline Profile 测试
// macrobenchmark/src/androidTest/java/…/BaselineProfileGenerator.kt
class BaselineProfileGenerator {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun generate() {
benchmarkRule.collectBaselineProfile(
packageName = "com.example.app",
profileBlock = {
startActivityAndWait(Intent()) // 冷启动
// 执行用户关键操作组合…
device.wait(Until.hasObject(By.text("Home")), 5_000)
// 例如点击首页按钮
device.findObject(By.text("开始")).click()
device.waitForIdle()
}
)
}
}
运行测试:
./gradlew :macrobenchmark:connectedCheck -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
运行后输出文件位于 macrobenchmark/build/outputs/managed_device_profile 或 macrobenchmark/build/generated 下,将其复制到主模块 src/main/baseline-prof.txt。
| 对比维度 | 手工生成 | 自动生成(Macrobenchmark) |
|---|---|---|
| 适用场景 | 已明确热点方法 | 真实用户路径覆盖 |
| 准确性 | 依赖开发者经验 | 精确反映首次组合路径 |
| 维护成本 | 每次修改需手动调整 | 随测试自动更新 |
| 配置复杂度 | 低(仅需文件) | 需创建 Macrobenchmark 模块 |
4.3 AGP 插件配置
从 AGP 7.3 开始,支持将 baseline-prof.txt 自动注入到编译流程中。只需在 app/build.gradle.kts 中启用即可(无需额外插件):
// app/build.gradle.kts
android {
...
buildFeatures {
// 开启 Baseline Profile 自动合并与编译
baselineProfile = true
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
设置后,Gradle 会在 release 构建时自动将 src/main/baseline-prof.txt 合并到 APK 的 assets/dexopt/baseline.prof 中,并在安装时被 ART 读取。
src/flavorName/baseline-prof.txt 中放置 flavor 专属规则;默认读取 src/main 中的文件。
4.4 Profile Installer 集成
为了在首次安装后立即生效,需要使用 Profile Installer 库在应用运行时触发 profile 写入。添加依赖:
// app/build.gradle.kts
dependencies {
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
}
库会自动在 第一次冷启动 时通过 BroadcastReceiver 机制将 baseline profile 写入设备内部存储,ART 随后加载。无需额外代码。
1. 安装 Release APK。
2. 运行
adb shell dumpsys package dexopt --baseline <package>,若输出包含 baseline.prof 路径且状态为 used,表示生效。3. 对比启动时间:集成后冷启动 Compose 界面应显著缩短(通常 30%-50%)。
4.5 常见错误与调优
- 错误:profile 未生效 —— 检查 APK 中是否包含
assets/dexopt/baseline.prof(aapt l <apk>查看),且文件名正确(需为baseline.prof)。 - 错误:规则过多导致构建慢 —— 限制在 400-600 条。使用
collectBaselineProfile生成的规则通常已精简。 - 优化:混合模式 —— 先用自动生成获得全量覆盖,再手工微调移除不必要的冷门方法。
- 兼容性 —— Profile Installer 1.3 起支持 Android 7+,但低版本设备需降级处理(通过
install-time而非update-time)。
4.6 全流程结构图
图中可见,无论采用手工还是自动方式,最终都需通过 AGP 配置将 profile 打入 APK,并依赖 Profile Installer 在设备上生效。实际项目中建议先用 Macrobenchmark 自动生成,再根据微调手动补充关键路径,实现精度与效率平衡。