在当今的移动应用世界中,顺畅的用户体验不仅是一项功能,更是一项必需品。加载时间过长、界面无响应和不稳定性可能会严重阻碍用户互动和留存。在与 Android 开发者关系团队合作期间,Reddit 的工程团队使用 App Performance Score 评估了他们的应用。在评估了应用性能后,他们发现应用有很大的改进潜力,并决定采取措施来充分发挥 R8(Android 应用优化器)的强大功能。这项重点计划显著缩短了启动时间,减少了缓慢或冻结的帧和 ANR,并全面提升了 Play 商店评分。本案例研究将详细介绍 Reddit 如何取得这些令人瞩目的成果。
R8 优化器如何帮助 Reddit
R8 优化工具是 Android 上用于优化性能的基础工具。需要采取各种步骤来提升应用性能。下面我们快速了解一下其中最有效的一些步骤。
- 摇树优化是缩减应用大小的最重要一步。在此阶段,系统会移除应用依赖项和应用本身中未使用的代码。
- 方法内联会将方法调用替换为实际代码,从而提高应用性能。
- 应用类合并和其他策略,使代码更紧凑。此时,我们不再关注源代码的人工可读性,而是要让编译后的代码快速运行。因此,接口或类层次结构等抽象概念在这里并不重要,将被移除。
- 标识符精简会将类、字段和方法的名称更改为更短且无意义的名称。因此,您最终可能会得到一个名为 a 的类,而不是
MyDataModel。 - 资源缩减 功能会移除未使用的资源(例如 XML 文件和可绘制对象),以进一步缩减应用大小。
R8 优化的主要阶段
从硬数据到用户满意度:确定生产环境中的成功
在向用户推出新版应用后,Reddit 立即看到了性能方面的改进。通过使用 Android Vitals 和 Crashlytics,Reddit 能够捕获实际用户在真实设备上的性能指标,从而将新版本与之前版本进行比较。
R8 如何提升 Reddit 的应用性能
该团队发现,冷启动速度提升了 40% ,“应用无响应”错误减少了 30% ,帧渲染提升了 25% ,应用大小减少了 14% 。
这些增强功能对于提高用户满意度至关重要。启动速度更快意味着等待时间更短,可以更快地访问内容。减少 ANR 可让应用更稳定可靠,从而减少用户的不满。更流畅的帧渲染可消除界面卡顿,使滚动和动画感觉流畅且响应迅速。这种积极的技术影响也清晰地体现在用户情绪中。
优化效果的用户满意度指标直接显示在 Google Play 商店中。在推出经过 R8 优化的版本后,该团队发现用户情绪和互动度发生了显著的积极转变。
Drew Heavner:“在不到 2 周的时间内,充分发挥 R8 的潜能”
最令人印象深刻的是,这项工作是通过集中精力完成的。Reddit 的软件工程师 Drew Heavner 参与了这项计划,他指出,实施这些变更以充分发挥 R8 的潜力不到两周。
确认增益:使用宏基准进行深入分析
在观察到显著的实际改进后,Reddit 的工程团队和 Google 的 Android 开发技术推广团队进行了详细的基准比较,以科学地确认这些增益,并尝试进一步优化。为了进行此分析,Reddit 工程团队提供了两个版本的应用:一个未进行优化,另一个应用了 R8 和另外两个基础性能优化工具:基准配置文件和启动配置文件。
基准配置文件可有效地将即时 (JIT) 编译步骤从用户设备转移到开发者机器上。生成的预先 (AOT) 编译代码已被证明可缩短启动时间并减少渲染问题。
应用打包时,d8 dexer 会获取类和方法,并构建应用的 classes.dex 文件。当用户打开应用时,系统会依次加载这些 dex 文件,直到应用可以启动为止。通过提供启动配置文件,您可以让 d8 知道要在第一个 classes.dex 文件中打包哪些类和方法。此结构可让应用加载更少的文件,从而提高启动速度。
Jetpack Macrobenchmark 是此阶段的核心工具,可在受控环境中精确测量用户互动。为了模拟典型的用户体验历程,他们使用 UIAutomator API 创建了一个测试,该测试会打开应用、向下滚动三次,然后再向上滚动。
最后,编写基准所需的全部内容如下:
uiAutomator {
startApp(REDDIT)
repeat(3) {
onView { isScrollable }.fling(Direction.DOWN) }
repeat(3) {
onView {isScrollable }.fling(Direction.UP)
}
}基准数据证实了实地观测结果,并提供了更深入的分析洞见。完全优化的应用启动速度提高了 55% ,用户可以提前 18% 开始浏览。优化后的应用还显示,即时 (JIT) 编译次数减少了三分之二,JIT 编译时间缩短了三分之一。帧呈现得到改进,在基准用户体验历程中,呈现的帧数增加了 19%。最终,应用的大小缩减了三分之一以上。
Reddit 的整体性能改进
您可以使用自定义 Macrobenchmark 轨迹部分指标来衡量 JIT 编译时间,如下所示:
val jitCompilationMetric = TraceSectionMetric("JIT Compiling %", label = "JIT compilation")启用转换背后的技术:R8
如需在完整模式下启用 R8,请在发布 build 类型中将 app/build.gradle.kts 文件配置为将 minifyEnabled 和 shrinkResources 设置为 true。
android {
...
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"keep-rules.pro",
)
}
}
}此步骤之后必须进行全面的端到端测试,因为性能优化可能会导致意外行为,最好在用户发现之前就发现这些行为。
如本文前面部分所示,R8 会执行广泛的优化,以最大限度地提升性能。R8 会对代码进行大幅修改,包括重命名、移动和移除类、字段和方法。如果您发现这些修改会导致错误,则需要通过在保留规则中声明代码的哪些部分不应被 R8 修改,来指定这些部分。
在应用中效仿 Reddit 的做法
Reddit 在使用 R8 方面取得的成功为任何希望以较低的成本显著提升应用性能的开发团队提供了一个强有力的案例研究。技术改进与随后的用户满意度提升之间的直接相关性凸显了性能优化的价值。
通过遵循本案例研究中提出的蓝图(使用应用性能得分等工具来发现机会、充分发挥 R8 的优化潜力、监控实际数据,并使用基准来确认和加深了解),其他开发者也能获得类似的收益。
如需在自己的应用中开始使用 R8,请参阅有关启用、配置和排查 R8 优化器问题的最新官方文档和指南。
-
案例研究Monzo 是一家英国数字银行,拥有 1,500 万客户,并且客户数量还在不断增长。随着应用规模的扩大,工程团队发现应用启动时间是一个需要改进的关键方面,但担心这需要对代码库进行重大更改。
Ben Weiss, Tracy Agyemang • 阅读用时:2 分钟 -
案例研究随着大多数 Android 应用都采用 Kotlin 作为其主要语言,kotlinx.coroutines 已成为异步编程的事实标准。该库提供了一种设计合理且结构化的方式来管理 Kotlin 原生的并发数据流。
Jonathan Starup, Andrei Shikov • 阅读用时:7 分钟 -
案例研究众所周知,性能下降问题很难重现,这使得性能下降成为移动开发者的巨大瓶颈。
每周通过电子邮件接收最新的 Android 开发洞见。