经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android基准配置文件Baseline?Profile方案提升启动速度
来源:jb51  时间:2023/2/6 9:00:45  对本文有异议

引言

偶然在Youtube上看到一名国外安卓开发者分享了一个提升应用性能的视频,其中使用到了macro benchmark来进行性能测量,包括启动速度和列表帧率,方法是生成一个baseline-prof.txt文件放于app/src/main/下。查阅google的官方文档,其背后原理如下:

通过在应用或库中分发基准配置文件,Android 运行时 (ART) 可以通过预先 (AOT) 编译来优化包含的代码路径,从而针对每位新用户以及每个应用更新提升性能。这种配置文件引导的优化 (PGO) 可让应用优化启动、减少互动卡顿,并提高整体的运行时性能,从而让用户从首次启动开始便获得更好的使用体验。

基准配置文件介绍

baseline-prof.txt文件中定义了安装时要预编译的代码路径,打包时会跟随aab一起上传到Google Play,通过Google play安装时将获得预编译的收益。

这个方案看起来很不错,相比于其它的那些难以上手的启动优化方案,这个似乎比较好落地,于是乎我开始了接入尝试,最后艰难成功了。

测量工具

官方建议使用Jetpack Macrobenchmark来测试应用在已启动基准配置文件时的性能,然后将这些结果与已停用基准配置文件时的基准进行比较。接入的方式也很简单,如果你的AS版本满足要求,File/New Module/Benchmark就可以了。

会在benchmark Module生成一个ExampleStartupBenchmark测试类,将其修改一下变成如下。

  1. @RunWith(AndroidJUnit4ClassRunner::class)
  2. class ColdStartupBenchmark {
  3. @get:Rule
  4. val benchmarkRule = MacrobenchmarkRule()
  5. /**
  6. * 不使用基准配置文件
  7. */
  8. @Test
  9. fun startupNoCompilation() = startup(CompilationMode.None() )
  10. /**
  11. * 使用基准配置文件模式
  12. */
  13. @Test
  14. fun startupBaselineProfile() = startup(CompilationMode.Partial())
  15. @Test
  16. fun startupFullCompilation() = startup(CompilationMode.Full())
  17. private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated(
  18. packageName = "com.example.macrobenchmark.target",
  19. metrics = listOf(StartupTimingMetric()),
  20. compilationMode = compilationMode,
  21. iterations = 10,
  22. startupMode = StartupMode.COLD,
  23. setupBlock = {
  24. pressHome()
  25. }
  26. ) {
  27. // Waits for the first rendered frame, which represents time to initial display.
  28. startActivityAndWait()
  29. // Waits for content to be visible, which represents time to fully drawn.
  30. //此处可删除,my-content根据自己项目首页的布局决定
  31. device.wait(Until.hasObject(By.res("my-content")), 5_000)
  32. }
  33. }

选择带有Benchmark后缀的build variant,测试结果如下所示:

ExampleStartupBenchmark_startUpCompilationModePartial
timeToInitialDisplayMs   min 290.7,   median 310.5,   max 391.2
Traces: Iteration 0 1 2 3 4

ExampleStartupBenchmark_startUpCompilationModeNone
timeToInitialDisplayMs   min 359.4,   median 381.9,   max 420.6
Traces: Iteration 0 1 2 3 4

timeToInitialDisplayMs - 从系统收到启动 intent 到渲染目标 activity 的第一帧的时间

timeToFullDisplayMs - 从系统收到启动 intent 到应用通过 reportFullyDrawn 方法报告已完成绘制的时间。这个需要你手动调用activity.reportFullDrawn()才会有结果展示,表示此时已完全绘制。

Trace: Iteration可以看到每次启动的trace记录,点击数字会跳到Profiler分析界面

运行的时候可能会遇到的问题:

有配置多渠道(Flavor),然后提示Run configuration ExampleStartupBenchmark is not supported in the current project.Cannot obtain the package.解决办法是benchmark里的flavor保持跟app模块一致就可以了

aar依赖找不到

  1. Could not determine the dependencies of null.
  2. Could not resolve all task dependencies for configuration':benchmark:flavorDemoBenchmarkTestedApks'.
  3. Could not find :your_aar_name_in_testModule_libs:.
  4. Required by:
  5. project :benchmark > project :app > project :testModule

解决方案:在benchmark模块的build.gradle中添加

  1. repositories {
  2. flatDir {
  3. dirs '../testModule/libs', '../app/libs'
  4. }
  5. }

Unable to read any metrics during benchmark因为benchmark模块中的benchmark buildtype中debuggable要设为true才行

官方文档

生成基准配置文件

在benchmark模块处新建一个测试类:

  1. @ExperimentalBaselineProfilesApi
  2. @RunWith(AndroidJUnit4::class)
  3. class BaselineProfileGenerator {
  4. @get:Rule val baselineProfileRule = BaselineProfileRule()
  5. @Test
  6. fun startup() =
  7. baselineProfileRule.collectBaselineProfile(packageName = "com.example.app") {
  8. pressHome()
  9. // This block defines the app's critical user journey. Here we are interested in
  10. // optimizing for app startup. But you can also navigate and scroll
  11. // through your most important UI.
  12. startActivityAndWait()
  13. }
  14. }

新建一个Android9以上版本模拟器(真机不行),注意系统选择不包含Google Api的,执行adb root命令,修改ndk filter添加支持,之后就可以跑上面新建的测试了,执行完成之后基准配置文件会生成于benchmark/build/outputs/connected_android_test_additional_output/flavorDemoBenchmark/Pixel 2处,名字类似于BaselineProfileGenerator_generateBaselineProfile-baseline-prof-2023-01-30-07-29-28.txt,将之拷贝到app/src/main/目录下,重命名为baseline-prof.txt。

官方文档

验证优化效果

万事俱备,只欠惊喜,验证一下对启动速度有多大提升。

在app模块添加以下依赖:

  1. dependencies {
  2. implementation("androidx.profileinstaller:profileinstaller:1.3.0-alpha03")
  3. }

连接真机再次跑ExampleStartupBenchmark测试,在不同机型分别得到的结果为:

Pixel 1: android 10

ExampleStartupBenchmark_compilationPartial  
timeToInitialDisplayMs   min 1,359.2,   median 1,422.4,   max 2,583.0  

ExampleStartupBenchmark_compilationNone  
timeToInitialDisplayMs   min 1,454.1,   median 1,556.7,   max 2,610.3 

三星S20: android 13

ExampleStartupBenchmark_compilationPartial
timeToInitialDisplayMs   min 597.2,   median 683.9,   max 763.4

ExampleStartupBenchmark_compilationNone
timeToInitialDisplayMs   min 699.5,   median 726.1,   max 753.5

三星S8+: android7

ExampleStartupBenchmark_compilationPartial  
timeToInitialDisplayMs   min 1,089.1,   median 1,121.6,   max 1,249.4 

ExampleStartupBenchmark_compilationNone  
timeToInitialDisplayMs   min 1,147.5,   median 1,166.2,   max 1,338.2

观察数据可以看出,总体来说有一定的提升,特别是在性能低一点的机器会比较明显,但相比于google官方给的文档中的示例结果(提升20%+)还有一点差距,猜测应该跟生成的baseline-prof.txt有关,因为我这里只生成了启动过程到完成第一帧绘制时的热点代码列表,google的例子是生成了到首页并且切换tab的热点代码。

此外,基准配置文件也可以用在提升首次打开操作流畅性上,原理也是一样的,只需要在BaselineProfileGenerator处添加首次进入之后的一些操作,比如像官方的例子一样的切换tab、列表滑动,生成新的文件即可。

以上就是Android基准配置文件Baseline Profile方案提升启动速度的详细内容,更多关于Android Baseline Profile提升启动速度的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号