操作指南

更深入的性能考虑因素

阅读用时:8 分钟

请冷静下来,让我们引导您了解有关性能的更多背景信息。

欢迎来到“性能聚焦周”的第 3 天。今天,我们将继续分享有关应用性能重要方面的详细信息和指南。我们将介绍配置文件引导的优化、Jetpack Compose 性能改进以及幕后故事的注意事项。让我们直接开始吧。

配置文件引导的优化

基准配置文件启动配置文件是提升 Android 应用的启动和运行时性能的基础。它们属于一组称为“配置文件引导的优化”的性能优化。

打包应用时,d8 dexer 会获取类和方法,并填充应用的 classes.dex 文件。当用户打开应用时,这些 dex 文件会依次加载,直到应用可以启动为止。通过提供启动配置文件 ,您可以让 d8 知道要在第一个 classes.dex 文件中打包哪些类和方法。这种结构允许应用加载较少的文件,从而提高启动速度。

基准配置文件有效地将即时 (JIT) 编译步骤从用户设备转移到开发者机器上。生成的提前 (AOT) 编译代码已被证明可以减少启动时间和渲染问题。

Trello 和基准配置文件

我们询问了 Trello 应用的工程师,基准配置文件对其应用的性能有何影响。在将基准配置文件应用于其主要用户历程后,Trello 的应用启动时间显著缩短了 25%。

image.png

Trello 通过使用基准配置文件,将其应用的启动时间缩短了 25%。

Meta 的基准配置文件

此外,Meta 的工程师最近发表了一篇文章,介绍了他们如何使用基准配置文件加速 Android 应用

image.png

在 Meta 的应用中,团队在应用基准配置文件后发现,各项关键指标的改进幅度高达 40%。

此类技术改进有助于您提高用户满意度和业务成功率。与产品负责人、首席技术官和决策者分享此信息也有助于加快应用的性能。

开始使用基准配置文件

如需生成基准配置文件或启动配置文件,您可以编写一个宏基准测试来执行应用。在测试期间,系统会收集配置文件数据,这些数据将在应用编译期间使用。这些测试是使用新的 UiAutomator API 编写的,我们将在明天介绍该 API。

编写此类基准非常简单,您可以在 GitHub 上查看完整示例。

@Test

fun profileGenerator() {

    rule.collect(

        packageName = TARGET_PACKAGE,

        maxIterations = 15,

        stableIterations = 3,

        includeInStartupProfile = true

    ) {

        uiAutomator {

            startApp(TARGET_PACKAGE)

        }

    }


}

注意事项

首先,为用户最常访问的路径编写宏基准测试基准配置文件和启动配置文件。这意味着用户进入应用的主要入口点,通常是在用户登录后。然后,继续编写更多测试用例,以便仅针对基准配置文件捕获更完整的图片。您无需使用基准配置文件涵盖所有内容。坚持使用最常用的路径,并在实际环境中衡量性能。有关这方面的更多信息,请参阅明天的博文。

开始使用配置文件引导的优化

如需了解基准配置文件在后台的运作方式,请观看 Android 开发者峰会的这段视频:

如需深入了解,请观看 Android Build Time 中有关配置文件引导的优化的剧集:

我们还提供了有关 基准配置文件和 启动配置文件的详细指南,供您进一步阅读。

Jetpack Compose 性能改进

Android 的界面框架已看到工程团队的性能投资获得回报。从 Jetpack Compose 1.9 版开始,在内部长滚动基准测试期间,滚动卡顿已降至 0.2%。

jankyFrames.png

这些改进之所以能够实现,是因为最新版本中包含多项功能。

可自定义的缓存窗口

默认情况下,延迟布局仅在滚动方向上提前组合一项,并且在某项滚动到屏幕外后,系统会将其舍弃。您现在可以通过视口或 dp 大小的一部分来自定义要保留的项目数量。这有助于您的应用提前执行更多工作,并在启用帧间可暂停组合后,更高效地利用可用时间。

如需开始使用可自定义的缓存窗口,请实例化 LazyLayoutCacheWindow 并将其传递给延迟列表或延迟网格。使用不同的缓存窗口大小(例如视口的 50%)衡量应用的性能。最佳值将取决于内容的结构和项目大小。

val dpCacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)

val state = rememberLazyListState(cacheWindow = dpCacheWindow)

LazyColumn(state = state) {

    // column contents

}

可暂停的组合

借助此功能,您可以暂停组合,并将其工作拆分为多个帧。这些 API 已在 1.9 中推出,现在在延迟布局预提取中默认使用 1.10。对于组合时间较长的复杂项目,您应该会看到最大的好处。

image.png

更多 Compose 性能优化

在 Compose 的 1.9 和 1.10 版本中,该团队还进行了一些不太明显的优化。

一些在后台使用协程的 API 得到了改进。例如,在使用 DraggableClickable 时,开发者应该会看到更快的响应时间和更高的分配计数。

布局矩形跟踪方面的优化提升了 onVisibilityChanged()onLayoutRectChanged() 等修饰符的性能。即使不明确使用这些 API,这也会加快布局阶段的速度。

另一项性能改进是在通过 onPlaced() 观察位置时使用缓存的值。

在后台预提取文本

从 1.9 版开始,Compose 添加了在后台线程上预提取文本的功能。这使您能够预热缓存以实现更快的文本布局,并且与应用渲染性能相关。在布局期间,文本必须传递到 Android 框架中,在其中填充字词缓存。默认情况下,此操作在界面线程上运行。将预提取和填充字词缓存卸载到后台线程上可以加快布局速度,尤其是对于较长的文本。如需在后台线程上预提取,您可以将自定义执行器传递给在后台使用 BasicText 的任何可组合项,方法是将 LocalBackgroundTextMeasurementExecutor 传递给 CompositionLocalProvider,如下所示。

val defaultTextMeasurementExecutor = Executors.newSingleThreadExecutor()

CompositionLocalProvider(

    LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor

) {

    BasicText("Some text that should be measured on a background thread!")


}

根据文本的不同,这可以提升文本渲染的性能。如需确保它能提升应用的渲染性能,请进行基准测试并比较结果。

后台工作性能注意事项

后台工作是许多应用的重要组成部分。您可以使用 WorkManager 或 JobScheduler 等库来执行以下任务:

  • 定期上传分析事件
  • 在后端服务和数据库之间同步数据
  • 处理媒体(即调整图片大小或压缩图片)

执行这些任务时面临的一个主要挑战是平衡性能和能效。WorkManager 可让您实现这种平衡。它旨在提高能效,并允许将工作推迟到最佳执行窗口,该窗口受多种因素的影响,包括您指定的限制或系统施加的限制。

不过,WorkManager 并非一体适用的解决方案。Android 还提供了许多经过能效优化的 API,这些 API 专门针对某些常见的核心用户历程 (CUJ) 而设计。  

如需查看其中一些 API 的列表,包括更新 widget 和在后台获取位置,请参阅后台工作着陆页

后台工作的本地调试工具:常见场景

如需调试后台工作并了解任务可能延迟或失败的原因,您需要了解系统如何调度任务。

为了帮助您解决此问题,WorkManager 提供了几个相关 工具,可帮助您在本地调试和优化性能(其中一些工具也适用于 JobScheduler)!以下是您在使用 WorkManager 时可能会遇到的一些常见场景,以及可用于调试这些场景的工具的说明。

调试预定工作未执行的原因

预定工作延迟或根本未执行可能是由多种因素造成的,包括未满足指定的限制或系统施加了限制

调查预定工作未运行原因的第一步是确认工作已成功预定 。 确认预定状态后,确定是否存在任何未满足的限制或前提条件阻止工作执行。

有多种工具可用于调试此场景。

后台任务检查器

后台任务检查器是一款功能强大的工具,直接集成到 Android Studio 中。它以直观的方式呈现所有 WorkManager 任务及其关联状态(正在运行、已排队、失败、成功)。

如需使用后台任务检查器调试预定工作未执行的原因,请参阅列出的工作状态。“已排队”状态表示您的工作已预定,但仍在等待运行。

优势: 除了提供一种查看所有任务的简单方法外,如果您有链接的工作,此工具尤其有用。后台任务检查器提供了一个图表视图,可以直观地显示先前任务失败是否可能影响后续任务的执行。

image.png

后台任务检查器列表视图

image.png

后台任务检查器图表视图

adb shell dumpsys jobscheduler

命令 会返回所有有效 JobScheduler 作业(包括 WorkManager 工作器)的列表,以及指定的限制和系统施加的限制。它还会返回作业历史记录。

如果您想以其他方式查看预定工作和关联的限制,请使用此命令。对于 WorkManager 2.10.0 之前的 WorkManager 版本,adb shell dumpsys jobscheduler 将返回一个包含以下名称的工作器列表:

[package name]/androidx.work.impl.background.systemjob.SystemJobService

如果您的应用有多个工作器,更新到 WorkManager 2.10.0 后,您将能够看到工作器名称并轻松区分工作器:

#WorkerName#@[package name]/androidx.work.impl.background.systemjob.SystemJobService

优势: 此命令有助于了解是否存在任何系统施加的限制, 而您无法使用后台任务检查器确定这些限制。例如,此命令将返回您的 应用的待机存储分区,这可能会影响预定工作完成的窗口。

启用调试日志记录

您可以启用 自定义日志记录,以查看详细的 WorkManager 日志,这些日志将附加 WM—

优势: 这样,您就可以了解工作何时预定、限制何时满足以及生命周期事件,并且您可以在开发应用时查阅这些日志。

WorkInfo.StopReason

如果您发现特定工作器的性能不可预测,可以使用 WorkInfo.getStopReason 以编程方式观察工作器在上一次运行尝试中停止的原因。 

最好将应用配置为使用 getWorkInfoByIdFlow 观察 WorkInfo,以确定您的工作是否受到后台限制、限制、频繁超时甚至用户停止的影响。

优势: 您可以使用 WorkInfo.StopReason 收集有关工作器性能的字段数据。

调试 Android Vitals 标记的 WorkManager 归因的高唤醒锁定持续时间

Android Vitals 具有“过度使用部分唤醒锁定”指标,该指标会突出显示导致耗电的唤醒锁定。您可能会惊讶地发现,WorkManager 会获取唤醒锁定来执行任务,并且如果唤醒锁定超出 Google Play 设置的阈值,可能会影响应用的曝光度。如何调试归因于工作的大量唤醒锁定持续时间的原因?您可以使用以下工具。

Android Vitals 信息中心

首先在 Android Vitals“过度唤醒锁定”信息中心内确认高唤醒锁定持续时间是否来自 WorkManager,而不是闹钟或其他唤醒锁定。您可以使用“识别由其他 API 创建的唤醒锁定”文档来了解哪些唤醒锁定是由于 WorkManager 而保留的。

Perfetto

Perfetto 是一款用于分析系统轨迹的工具。当您专门使用它来调试 WorkManager 时,可以查看“设备状态”部分,了解工作何时开始、运行时间以及对功耗的影响。

在“设备状态:作业”轨迹下,您可以看到已执行的任何工作器及其关联的唤醒锁定。

deviceState.png

Perfetto 中的“设备状态”部分,显示 CleanupWorker 和 BlurWorker 的执行情况。

资源

如需大致了解您可能会遇到的其他场景的可用调试方法,请参阅调试 WorkManager 页面

如需亲手尝试其中一些方法并详细了解如何调试 WorkManager,请参阅 WorkManager 高级和测试 Codelab。

后续步骤

今天,我们超越了代码缩减,探讨了 Android 运行时和 Jetpack Compose 如何实际渲染应用。无论是使用基准配置文件预编译关键路径,还是使用新的 Compose 1.9 和 1.10 功能平滑滚动状态,这些工具都专注于应用的 体验。我们还深入探讨了调试后台工作的最佳实践。

Ask Android

周五,我们将举办一场关于性能的直播 AMA。立即使用 #AskAndroid 提出问题,并获得专家的解答。

面临的挑战

周一,我们向您发起了启用 R8 的挑战。今天,我们要求您为应用生成一个基准配置文件

借助 Android Studio Otter,基准配置文件生成器模块向导使此操作比以往任何时候都更加轻松。选择最重要的用户历程(即使只是应用启动和登录),然后生成配置文件。

生成配置文件后,运行宏基准测试以比较 CompilationMode.NoneCompilationMode.Partial

使用 #optimizationEnabled 在社交媒体上分享启动时间改进情况。

明天收看

您已使用 R8 缩减了应用,并使用配置文件引导的优化功能优化了运行时。但是,您如何向利益相关者证明这些优势?如何在回归影响生产环境之前捕获它们?

欢迎明天收看第 4 天:性能调平指南,我们将详细介绍如何衡量您的成功,从 Play Vitals 中的实际环境数据到使用 Perfetto 进行深入的本地跟踪。

继续阅读