本文主要记录 Android Developers 关于 R8 加速 Kotlin 协程的机制、在自托管媒体客户端仓库里「门槛已到但默认吃不到」的差距,以及用 minify 开/关做体积与冷启动对照时的结论边界。官方 2× 数字不能直接写成自家产品实测。

2026-07 官方博文说明:自 AGP 9.2.0 起,R8 会把多数静态可分析的 Atomic*FieldUpdater 调用改写为 Unsafe 变体,去掉反射安全检查,从而让 kotlinx.atomicfu / kotlinx.coroutines 的 launch、cancel 等路径显著变快;Compose LaunchedEffect 微基准约有 2× 量级改善。

对真实 App 来说,问题往往是:工具链版本够了,但 release 没开 minify,全程序优化根本没跑。

官方机制在做什么

kotlinx.coroutines 的 lock-free 结构大量依赖 AtomicReferenceFieldUpdater 一类按「类 + 字段名」做运行时原子访问的路径,每次操作伴随反射安全检查。官方在 Pixel 5 一类设备上测到 atomicfu 的 CAS 可显著慢于 AtomicReference

R8 对静态可分析模式大致做三步:

  1. Instrumentation:旁路生成 field offset
  2. Replacement:调用点替换为 Unsafe 原子操作
  3. Clean-up:删除已无用的 updater 字段与初始化

门槛与并行路径:

路径条件官方表述收益量级
R8 编译期改写AGP ≥ 9.2.0(或 R8 9.2+)原子操作约 2×–4×;协程 launch/cancel 最高约 2×
ART 运行时较新 ART / 高 target API协程基准约 +15% 量级(与 R8 并行)

博文写升级 AGP 即可「by default」获得优化,但未逐字写死必须 isMinifyEnabled = true。按常规 AGP 语义,R8 全程序 shrink / optimize 发生在 开启 minify 的变体。在未开 minify 的产物上,应假设 拿不到 该改写,除非用开/关对照或 R8 日志证明。

仓库类客户端的常见差距

以含 Compose + Media3 + 自建 native(如 libmpv)的 Android 客户端为例,调研时常看到:

常见事实
AGP已到 9.2.x
minify / shrinkdebug / release 均未
proguard 业务规则无项目级 proguard-rules 接入
release 已有差异可能仅 native 日志宏、debuggable 等,不是 Java/Kotlin R8

此时:

  • 官方协程加速 通常不作用 于现有发布 APK。
  • 历史上若把 R8 和「剥 release 日志」绑在一起讨论,会错误放大风险:日志门控应继续靠 BuildConfig / 编译期宏,不要指望 R8 替业务剥日志。

热路径形态对齐(推断,非 profiling)

区域与官方场景关系
大量 LaunchedEffect / 手势交互贴近;可能先受益
媒体墙滑动、OSD 频繁重启 effect可能贴近
播放 session 长生命周期轮询相对不贴近 微基准式高频 launch/cancel

推断:若 Atomic 改写生效,更可能先体现在 Compose 交互与 UI 调度 的尖峰,而不是「打开一个播放 session」本身。

为何不能「直接默认 minify」

Media 客户端 minify 的 keep 面通常包括:

  • Media3 / 自建 decoder AAR、反射探测类名
  • libass / libmpv / JNI 相关类
  • SignalR / 序列化回调
  • Compose、Room、OkHttp 等 consumer rules 未覆盖的边角

已经出现过的一类真实坑:字符串 Class.forName("…AssHandler") 在 R8 改名后探测假阴性——应改为硬 Class 引用 + 明确 keep,而不是继续依赖脆弱字符串。

目标函数建议按优先级固定:

  1. 正确性(双引擎播放、字幕、session、TV 焦点等核心路径)
  2. 包体积(相对未 minify 基线可复现下降)
  3. 性能(有数据再写;无数据标未量化)

明确排除:用 R8 替代业务日志门控;把官方 2× 写成自家数字。

对照采样(脱敏结论)

在同一源码状态下,对某一 channel 的 edge + release 做 minify 关/开对照( 开 resource shrink;设备与路径已脱敏):

体积

变体APK 约相对
baseline(未 minify)~82.8 MiB
minify(R8)~44.7 MiB约 −46%

zip 未压缩分项上,缩减几乎全在 dexlib(native so)基本不变。结论:minify 显著缩小 APK;剩余体积由 native 主导

冷启动(同协议、去首 median)

含义相对 baseline(minify)
Aam start -W 的 TotalTime−20% 量级(约 −0.1s)
B到首页内容就绪的墙钟−20% 量级(约 −1.5s)

B 段含 uiautomator 探测开销,只适合 同协议对照,不宜解读为纯业务 CPU 时间。也 不是 官方协程 2× 微基准的复现。

推荐路线

选项做法建议
维持现状默认关闭 minify无证据前,默认发布可保持
探测 minify本地/旁路打开,不进默认 channel专项主路径
默认 minify + shrink写入 release 并进全渠道仅当探测证据充分
指望 ART +15%不 minify不能替代专项

实践顺序:

  1. 锁定目标 = 体积 + 性能 + 正确性(排除日志门控重构)
  2. 固定 channel / ABI / 是否 shrink resources 的口径
  3. 迭代 keep + 双引擎 / 字幕 / 登录 CUJ
  4. 有 mapping 归档策略后再考虑默认开启

相关阅读

参考与边界