docs: 同步 Baseline Profile 与 Startup Profile 双产物说明

This commit is contained in:
xfy 2026-06-16 09:54:38 +08:00
parent 6f4fa68f0d
commit ade852208b
11 changed files with 73 additions and 45 deletions

View File

@ -8,7 +8,7 @@
|------|------|------|
| `:core` | `com.android.library` | 所有 Compose UI、ViewModel、业务逻辑 |
| `:app` | `com.android.application` | 薄壳MainActivity + Manifest + 主题 |
| `:macrobenchmark` | `com.android.test` | Baseline Profile 生成 |
| `:macrobenchmark` | `com.android.test` | Baseline Profile / Startup Profile 生成 |
**铁律**`:app` 不添加业务逻辑,所有代码写在 `:core`
@ -22,9 +22,9 @@
./gradlew spotlessApply # 格式化ktlint
```
Baseline Profile 和性能追踪需连接设备:
Baseline Profile / Startup Profile 和性能追踪需连接设备:
```bash
./gradlew :macrobenchmark:updateBaselineProfile # 生成 + 自动复制到 core/src/main/baseline-prof.txt
./gradlew :macrobenchmark:updateBaselineProfile # 生成并复制两份 Profile 到 :core
./scripts/profile.sh # 默认 8 秒,输出到 logs/
```
@ -78,8 +78,8 @@ Baseline Profile 和性能追踪需连接设备:
| 文件 | 内容 |
|------|------|
| `CLAUDE.md` | 完整架构说明、组件树、动画机制、Pager 映射逻辑 |
| `DEVELOPMENT.md` | 性能追踪、Baseline Profile、模拟器启动参数 |
| `DEVELOPMENT.md` | 性能追踪、Baseline Profile / Startup Profile、模拟器启动参数 |
| `COMMENTS.md` | KDoc 规范、注释原则、反模式清单 |
| `app/AGENTS.md` | `:app` 模块细则 |
| `core/AGENTS.md` | `:core` 模块细则 |
| `macrobenchmark/AGENTS.md` | Baseline Profile 模块细则 |
| `macrobenchmark/AGENTS.md` | Baseline Profile / Startup Profile 模块细则 |

View File

@ -5,6 +5,15 @@ All notable changes to the YaYa project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- 修正 `:macrobenchmark` 将 Startup Profile 误当作 Baseline Profile 使用的问题。
`updateBaselineProfile` Task 现在会同时复制 `*-baseline-prof.txt``core/src/main/baseline-prof.txt`
以及 `*-startup-prof.txt``core/src/main/baselineProfiles/startup-prof.txt`,使 AOT 编译优化与 DEX layout 优化同时生效。
- 同步更新所有相关文档(`AGENTS.md``README.md``DEVELOPMENT.md``CLAUDE.md`
`macrobenchmark/AGENTS.md``BaselineProfileGenerator.kt`),明确区分 Baseline Profile 与 Startup Profile。
## [1.1.0] - 2026-06-02
### Added
@ -236,10 +245,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Aliyun Maven mirrors (switched back to Maven Central / Google)
- Unused Compose runtime ProGuard keep rules
## [Unreleased]
- No unreleased changes at this time.
---
[1.1.0]: https://github.com/xfy/yayacal/releases/tag/v1.1.0

View File

@ -29,7 +29,7 @@ Gradle configuration cache and build cache are enabled by default (`gradle.prope
**Three-module structure:**
- `:core` — all Compose UI, ViewModel, and business logic (`com.android.library`)
- `:app` — thin Android shell (`MainActivity``App()`)
- `:macrobenchmark` — Macrobenchmark module for Baseline Profile generation
- `:macrobenchmark` — Macrobenchmark module for Baseline Profile / Startup Profile generation
**Calendar UI composition** (all in `plus.rua.project.ui`):
```

View File

@ -39,7 +39,7 @@ trace 中包含自定义标记:
- `getMonthDays:*` — ViewModel 月份网格计算
- `VM:collapseProgress:*` — 折叠动画拖拽onDrag/onDragEnd/onExpandDrag/onExpandDragEnd
## Baseline Profile
## Baseline Profile / Startup Profile
```bash
# 编译 Android debug APK
@ -48,29 +48,37 @@ trace 中包含自定义标记:
# 安装到设备
./gradlew :app:installDebug
# 编译 release APK含 Baseline Profiles
# 编译 release APK含 Baseline / Startup Profiles
./gradlew :app:assembleRelease
# 安装 benchmark 构建类型 APK
./gradlew :app:installBenchmark
```
Baseline Profile 自动生成器。
一键生成并复制到 `:core`
运行方式(一键生成 + 自动复制到 :core
```
```bash
./gradlew :macrobenchmark:updateBaselineProfile
```
生成后会得到两份产物:
| 产物 | 目标路径 | 用途 |
|------|--------|------|
| Baseline Profile | `core/src/main/baseline-prof.txt` | 指导 ART 做 AOT 编译 |
| Startup Profile | `core/src/main/baselineProfiles/startup-prof.txt` | 指导 AGP 做 DEX layout 优化 |
仅运行基准测试(不自动复制):
```
```bash
./gradlew :macrobenchmark:connectedBenchmarkAndroidTest
```
手动复制路径:
`macrobenchmark/build/outputs/connected_android_test_additional_output/`
注意:当前 `benchmark` 构建类型继承自 `release``isMinifyEnabled = true`),因此生成的文本 profile 会包含 R8 混淆后的类/方法名。AGP 在打包 APK/AAB 时会根据最终混淆映射将其转换为二进制 profile这是正常行为。
## 模拟器
```sh

View File

@ -20,7 +20,7 @@
- `kotlinx-datetime` 处理所有日期逻辑
- `tyme4kt` 提供农历、节气与传统节日
- `sketch` 渲染动画 WebP
- 三模块:`:core`UI + 逻辑) · `:app`(薄壳) · `:macrobenchmark`Baseline Profile 生成)
- 三模块:`:core`UI + 逻辑) · `:app`(薄壳) · `:macrobenchmark`Baseline Profile / Startup Profile 生成)
## 构建
@ -37,8 +37,8 @@
./gradlew :core:testDebugUnitTest # 运行全部测试
./gradlew :core:testDebugUnitTest --tests "plus.rua.project.ui.CalendarUtilsTest" # 运行单个测试
# Baseline Profile需要连接设备
./gradlew :macrobenchmark:updateBaselineProfile # 一键生成 + 自动复制到 :core
# Baseline Profile / Startup Profile(需要连接设备)
./gradlew :macrobenchmark:updateBaselineProfile # 生成并复制两份 Profile 到 :core
./gradlew :macrobenchmark:connectedBenchmarkAndroidTest # 仅运行基准测试
# 性能 Profiling需要连接设备

View File

@ -54,7 +54,7 @@ android {
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks += listOf("release")
// isDebuggable=false 使 macrobenchmark 在模拟器上稳定运行,且 Partial 编译模式可用。
// 代价是生成的 baseline-prof.txt 会包含 R8 混淆后的类名;功能上仍然有效。
// 代价是生成的 baseline-prof.txt / startup-prof.txt 会包含 R8 混淆后的类名;功能上仍然有效。
// 若需要可人工维护的可读 profile请在真机上使用 debuggable build 或引入 Baseline Profile Gradle plugin。
isDebuggable = false
}

View File

@ -1,4 +1,4 @@
# Baseline Profiles 保留规则:确保方法名不被 R8 混淆,使 profile 规则匹配正确
# Baseline Profile / Startup Profile 保留规则:确保方法名不被 R8 混淆,使 profile 规则匹配正确
-keepattributes SourceFile,LineNumberTable
# ========== 第三方库保留 ==========

View File

@ -1,30 +1,32 @@
<!-- Parent: ../AGENTS.md -->
<!-- Generated: 2026-05-22 | Updated: 2026-05-22 -->
<!-- Generated: 2026-05-22 | Updated: 2026-06-15 -->
# macrobenchmark
## Purpose
宏基准测试模块,使用 Android Baseline Profile 技术自动生成启动优化配置文件。通过 UI Automator 模拟真实用户交互路径,收集 AOT 编译所需的 profile 数据。
宏基准测试模块,使用 Android Baseline Profile / Startup Profile 技术自动生成启动优化配置文件。通过 UI Automator 模拟真实用户交互路径,收集 AOT 编译与 DEX layout 优化所需的 profile 数据。
## Key Files
| File | Description |
|------|-------------|
| `build.gradle.kts` | 模块构建配置(`com.android.test` 插件、benchmark 构建类型、Baseline Profile 自动复制任务) |
| `build.gradle.kts` | 模块构建配置(`com.android.test` 插件、benchmark 构建类型、Baseline/Startup Profile 自动复制任务) |
## Subdirectories
| Directory | Purpose |
|-----------|---------|
| `src/main/java/plus/rua/project/baseline/` | Baseline Profile 生成器(见 `src/main/java/plus/rua/project/baseline/AGENTS.md` |
| `src/main/java/plus/rua/project/baseline/` | Baseline Profile / Startup Profile 生成器与冷启动基准测试(见 `src/main/java/plus/rua/project/baseline/AGENTS.md` |
## For AI Agents
### Working In This Directory
- 修改此模块需连接 Android 设备/模拟器运行
- Baseline Profile 一键生成:`./gradlew :macrobenchmark:updateBaselineProfile`
- Baseline / Startup Profile 一键生成:`./gradlew :macrobenchmark:updateBaselineProfile`
- 仅运行基准测试:`./gradlew :macrobenchmark:connectedBenchmarkAndroidTest`
- 生成的 profile 自动复制到 `core/src/main/baseline-prof.txt`
- 生成的两份产物自动复制到:
- `core/src/main/baseline-prof.txt`Baseline Profile用于 AOT
- `core/src/main/baselineProfiles/startup-prof.txt`Startup Profile用于 DEX layout
### Testing Requirements
- 需要已安装应用的 benchmark 构建类型
@ -34,7 +36,7 @@
### Internal
- `:app` 模块 — 目标测试应用
- `:core` 模块 — profile 自动复制到 `core/src/main/baseline-prof.txt`
- `:core` 模块 — Baseline/Startup Profile 自动复制目标模块
### External
- `androidx.benchmark:benchmark-macro-junit4`

View File

@ -4,7 +4,7 @@
<!--
Macrobenchmark 模块的 AndroidManifest。
该模块为 com.android.test 类型,通过 targetProjectPath 指向 :app 模块。
在 benchmark 构建类型下运行,自动生成 baseline-prof.txt。
在 benchmark 构建类型下运行,自动生成 baseline-prof.txt 与 startup-prof.txt
-->
</manifest>

View File

@ -4,15 +4,15 @@
# baseline
## Purpose
Baseline Profile 自动生成器与启动性能基准测试。包含:
- `BaselineProfileGenerator.kt`:通过 UI Automator 模拟核心用户交互路径冷启动、FAB 展开、显示调休切换、CalendarPager 翻页、日期选择、BottomCard 折叠/展开),生成 AOT 编译优化所需的 startup profile
Baseline Profile / Startup Profile 自动生成器与启动性能基准测试。包含:
- `BaselineProfileGenerator.kt`:通过 UI Automator 模拟核心用户交互路径冷启动、FAB 展开、显示调休切换、CalendarPager 翻页、日期选择、BottomCard 折叠/展开),同时生成 Baseline ProfileAOT与 Startup ProfileDEX layout两份产物
- `StartupBenchmark.kt`:冷启动性能基准测试,测量 `timeToInitialDisplay``timeToFullDisplay`
## Key Files
| File | Description |
|------|-------------|
| `BaselineProfileGenerator.kt` | Profile 生成测试类,覆盖启动与核心交互路径 |
| `BaselineProfileGenerator.kt` | Profile 生成测试类,覆盖启动与核心交互路径,生成 `*-baseline-prof.txt``*-startup-prof.txt` |
| `StartupBenchmark.kt` | 冷启动基准测试类,覆盖 Full/Partial/None 三种编译模式 |
## Subdirectories
@ -27,6 +27,8 @@ Baseline Profile 自动生成器与启动性能基准测试。包含:
### Testing Requirements
- 生成 Profile`./gradlew :macrobenchmark:updateBaselineProfile`
- Baseline Profile 输出:`core/src/main/baseline-prof.txt`
- Startup Profile 输出:`core/src/main/baselineProfiles/startup-prof.txt`
- 运行冷启动基准(仅该类):`./gradlew :macrobenchmark:connectedBenchmarkAndroidTest --tests "plus.rua.project.baseline.StartupBenchmark"`
- 需要设备/模拟器连接,应用已安装在 benchmark 构建类型下

View File

@ -14,7 +14,7 @@ import org.junit.Test
import org.junit.runner.RunWith
/**
* Baseline Profile 自动生成器
* Baseline Profile / Startup Profile 自动生成器
*
* 运行方式一键生成 + 自动复制到 :core
* ```
@ -29,19 +29,30 @@ import org.junit.runner.RunWith
* 手动复制路径
* `macrobenchmark/build/outputs/connected_android_test_additional_output/`
*
* 测试覆盖启动与核心用户交互路径实现关键路径 AOT
* 说明
* - `includeInStartupProfile = true` 会同时生成两份产物
* - `*-baseline-prof.txt`用于 ART AOT 编译优化
* - `*-startup-prof.txt`用于 AGP DEX layout 优化
* - `updateBaselineProfile` Task 会分别将它们复制到
* - `core/src/main/baseline-prof.txt`
* - `core/src/main/baselineProfiles/startup-prof.txt`
*
* 测试覆盖启动与核心用户交互路径用于 AOT DEX layout 优化
* 1. 冷启动 首帧渲染
* 2. 显示调休切换 ON/OFFDayCell 大规模重组 + staggered 动画
* 3. CalendarPager 翻页 "今天"按钮跳回
* 4. 跨月日期点击 自动跳转
* 5. DayCell 点击
* 6. BottomCard 拖拽折叠到周视图
* 7. 周视图左右翻页
* 8. BottomCard 拖拽展开回月视图
* 9. CalendarPager 左右翻页
* 2. 切换"显示调休"ONDayCell 大规模重组 + staggered 动画
* 3. CalendarPager 右滑 上一个月
* 4. 点击"今天"按钮跳回当月
* 5. 点击跨月日期 自动跳转
* 6. 再次点击"今天"跳回当月
* 7. 点击 DayCell
* 8. 拖拽 BottomCard 折叠到周视图
* 9. 周视图左右翻页
* 10. 拖拽 BottomCard 展开回月视图
* 11. 切换"显示调休"OFF
* 12. CalendarPager 左右翻页
*
* 年视图关于/开源许可工具/日期检查器等路径在部分模拟器上不稳定
* 暂时从生成流程中移除以保证 Baseline Profile 可稳定生成后续可在真机上扩展覆盖
* 暂时从生成流程中移除以保证 Profile 可稳定生成后续可在真机上扩展覆盖
*/
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
@ -169,7 +180,7 @@ class BaselineProfileGenerator {
device.waitForIdle()
}
Log.d(TAG, "Baseline profile 生成完成,核心路径已覆盖")
Log.d(TAG, "Baseline Profile / Startup Profile 生成完成,所有路径已覆盖")
}
)
}