安卓启动 性能提升 20-30% ,基准配置 入门教程

1.先从官方下载demohttps://github.com/android/codelab-android-performance/archive/refs/heads/main.zip

2.先用Android studio打开里面的baseline-profiles项目

3.运行一遍app,这里建议用模拟器,(Pixel 6 API 34)设备运行,因为基准配置 需要root权限,如果手机没有root,就用模拟器运行。

4.运行时会报This version (1.4.5) of the Compose Compiler requires Kotlin version 1.8.20 but you appear to be using Kotlin version 1.9.22 which is not known to be compatible.  Please consult the Compose-Kotlin compatibility map located at https://developer.android.com/jetpack/androidx/releases/compose-kotlin to choose a compatible version pair (or `suppressKotlinVersionCompatibilityCheck` but don't say I didn't warn you!).

5.修改libs.versions.toml里的 kotlin = "1.9.22" 改为 kotlin = "1.8.20"

6.再运行一下,private fun NavBackStackEntry.lifecycleIsResumed() = this.getLifecycle().currentState == Lifecycle.State.RESUMED 这里的getLifecycle()会报错,改成lifecycle

7.再运行一次,这一次应该可以启动成功了,图片不显示可以忽悠不管,因为这个图片是从谷歌那边加载过来的,需要飞机,我们重点是基准配置,如果前面步骤碰见其他问题,基本与该项目无关,可以自行百度和AI解决。

8.点击File->new module 选择baseline profile generator ,如图,如果你是java党,可以右边改改配置,因人而异,我这里就选择默认的kotlin,直接点finish

9.如果你碰见 配置文件一片红,就删除,重新创建,放app下面,就不会爆红了,如果你没有遇见以下问题,可以跳过此步

如果删不掉,是因为app在引用,把这段去掉,点击sync now,再重新删一下

10.在baselineprofile的build.gradle.kts文件中修改,添加代码如下,代码解释:useConnectedDevices = false意思是否在真机上运行,由于真机没有root,只能在模拟器上运行,所以选择false就行,然后配置模拟器 ,记得导入

import com.android.build.api.dsl.ManagedVirtualDevice
import com.android.build.api.dsl.ManagedVirtualDeviceandroid {.......................
.......................targetProjectPath = ":app"testOptions.managedDevices.devices {create<ManagedVirtualDevice>("pixel6Api31") {device = "Pixel 6"apiLevel = 31systemImageSource = "aosp"}}
}// This is the configuration block for the Baseline Profile plugin.
// You can specify to run the generators on a managed devices or connected devices.
baselineProfile {managedDevices += "pixel6Api31"useConnectedDevices = false
}

如图下

11.在baselineprofile找到BaselineProfileGenerator类,自己项目可以根据自己情况更改,但是由于我们是demo,就演示一下,代码如下

  @Testfun generate() {// This example works only with the variant with application id `com.example.baselineprofiles_codelab`."rule.collect(packageName = "com.example.baselineprofiles_codelab",// See: https://d.android.com/topic/performance/baselineprofiles/dex-layout-optimizationsincludeInStartupProfile = true) {// This block defines the app's critical user journey. Here we are interested in// optimizing for app startup. But you can also navigate and scroll through your most important UI.// Start default activity for your apppressHome()startActivityAndWait()// TODO Write more interactions to optimize advanced journeys of your app.// For example:// 1. Wait until the content is asynchronously loaded// 2. Scroll the feed content// 3. Navigate to detail screen// 1. Wait until the content is asynchronously loaded.waitForAsyncContent()// 2. Scroll the feed content.scrollSnackListJourney()// 3. Navigate to detail screen.goToSnackDetailJourney()// Check UiAutomator documentation for more information how to interact with the app.// https://d.android.com/training/testing/other-components/ui-automator}}fun MacrobenchmarkScope.waitForAsyncContent() {device.wait(Until.hasObject(By.res("snack_list")), 5_000)val contentList = device.findObject(By.res("snack_list"))// Wait until a snack collection item within the list is rendered.contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)}fun MacrobenchmarkScope.scrollSnackListJourney() {val snackList = device.findObject(By.res("snack_list"))// Set gesture margin to avoid triggering gesture navigation.snackList.setGestureMargin(device.displayWidth / 5)snackList.fling(Direction.DOWN)device.waitForIdle()}fun MacrobenchmarkScope.goToSnackDetailJourney() {val snackList = device.findObject(By.res("snack_list"))val snacks = snackList.findObjects(By.res("snack_item"))// Select snack from the list based on running iteration.val index = (iteration ?: 0) % snacks.sizesnacks[index].click()// Wait until the screen is gone = the detail is shown.device.wait(Until.gone(By.res("snack_list")), 5_000)}

12.点击run按钮旁边三颗点,选择Edit Configurations...,然后点击左上角+,添加Gradle,在RUN下面一行添加:app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile,点击OK就行,然后运行,如图:

如果出现> 'compileNonMinifiedReleaseJavaWithJavac' task (current target is 1.8) and 'compileNonMinifiedReleaseKotlin' task (current target is 17) jvm target compatibility should be set to the same Java version.
  Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain

把compileOptions里的兼容版本改成对应的版本就行了,由于我是用的java 17,就改成17就行了,然后重新运行

compileOptions {sourceCompatibility = JavaVersion.VERSION_17targetCompatibility = JavaVersion.VERSION_17
}

如果没有出现上面问题,可以忽悠不管

13.运行大概需要等5-6分钟,如果太久了,建议重新运行一下,因设备而异,运行完成的话,在app项目的src->release->generated->baselineProfiles文件下,生成2个txt文件,一个是1.8W行-2.5W行的baseline-prof.txt文件和startup-prof.txt文件,因项目而异,如果基准配置更多,生成的可能更多,由于我们只生成了,异步加载,点击,滚动,差不多2W行

如图:

14. 使用模拟器测试速度,在 baselineprofile 的 build.gradle.kts下的defaultConfig 里添加 testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "EMULATOR",代码解释,这段是用来印制模拟器的错误

defaultConfig {minSdk = 28targetSdk = 34testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "EMULATOR"
}

15.在baselineprofile 项目的StartupBenchmarks类里添加和前面基准配置的 代码一样,模拟和基准操作

代码如下:

  private fun benchmark(compilationMode: CompilationMode) {// This example works only with the variant with application id `com.example.baselineprofiles_codelab`."rule.measureRepeated(packageName = "com.example.baselineprofiles_codelab",metrics = listOf(StartupTimingMetric()),compilationMode = compilationMode,startupMode = StartupMode.COLD,iterations = 10,setupBlock = {pressHome()},measureBlock = {startActivityAndWait()waitForAsyncContent()// 2. Scroll the feed content.scrollSnackListJourney()// 3. Navigate to detail screen.goToSnackDetailJourney()})}fun MacrobenchmarkScope.waitForAsyncContent() {device.wait(Until.hasObject(By.res("snack_list")), 5_000)val contentList = device.findObject(By.res("snack_list"))// Wait until a snack collection item within the list is rendered.contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)}fun MacrobenchmarkScope.scrollSnackListJourney() {val snackList = device.findObject(By.res("snack_list"))// Set gesture margin to avoid triggering gesture navigation.snackList.setGestureMargin(device.displayWidth / 5)snackList.fling(Direction.DOWN)device.waitForIdle()}fun MacrobenchmarkScope.goToSnackDetailJourney() {val snackList = device.findObject(By.res("snack_list"))val snacks = snackList.findObjects(By.res("snack_item"))// Select snack from the list based on running iteration.val index = (iteration ?: 0) % snacks.sizesnacks[index].click()// Wait until the screen is gone = the detail is shown.device.wait(Until.gone(By.res("snack_list")), 5_000)}

16.然后,直接右键运行,这个测试类,在模拟器(Pixel 6 API 31) 以上运行,我建议在模拟器(Pixel 6 API 34)运行,因为API31,可能会报下面错误,如果出现了,就切到API34

如果出现了java.lang.IllegalStateException: Error: did not detect tracing on after 5000 ms  ,我建议切换到模拟器(Pixel 6 API34),运行就不有问题17.运行效果如下

StartupBenchmarks_startupCompilationBaselineProfiles
timeToFullDisplayMs      min   821.2,   median   908.4,   max 1,114.1
timeToInitialDisplayMs   min   438.9,   median   514.8,   max   678.4
Traces: Iteration 0 1 2 3 4 5 6 7 8 9
Timed out waiting for process (com.example.baselineprofiles_codelab) to appear on Pixel_6_API_34 [emulator-5556].
WARNING: Running on Emulator
Benchmark is running on an emulator, which is not representative of
real user devices. Use a physical device to benchmark. Emulator
benchmark improvements might not carry over to a real user's
experience (or even regress real device performance).

StartupBenchmarks_startupCompilationNone
timeToFullDisplayMs      min   984.5,   median 1,157.2,   max 1,257.2
timeToInitialDisplayMs   min   498.9,   median   606.3,   max   668.4
Traces: Iteration 0 1 2 3 4 5 6 7 8 9

StartupBenchmarks_startupCompilationNone 表示没有基准上运行

StartupBenchmarks_startupCompilationBaselineProfiles 表示在有基准上运行

1,157.2 ->908.4,提升大概200毫秒,差不多百分之20多,到这里教程就结束了,谢谢大家

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/339000.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

未来已来:Spring Boot引领数据库智能化革命

深入探讨了Spring Boot如何与现代数据库技术相结合&#xff0c;预测并塑造未来的数据访问趋势。本书不仅涵盖了Spring Data JPA的使用技巧&#xff0c;还介绍了云原生数据库的概念&#xff0c;微服务架构下的数据访问策略&#xff0c;以及AI在数据访问层的创新应用。旨在帮助开…

【docker】docker的安装

如果之前安装了旧版本的docker我们需要进行卸载&#xff1a; 卸载之前的旧版本 卸载 # 卸载旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc # 卸载历史版本 apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker…

Redis学习笔记【实战篇--短信登录】

开篇导读 实战篇有什么样的内容 短信登录 这一块我们会使用redis共享session来实现 商户查询缓存 通过本章节&#xff0c;我们会理解缓存击穿&#xff0c;缓存穿透&#xff0c;缓存雪崩等问题&#xff0c;让小伙伴的对于这些概念的理解不仅仅是停留在概念上&#xff0c;更…

mfc140u.dll丢失的解决方法有哪些?怎么全面修复mfc140u.dll文件

mfc140u.dll丢失其实相对来说不太常见到&#xff0c;因为这个文件一般是不丢失的&#xff0c;不过既然有人遇到这种问题&#xff0c;那么小编一定满足各位&#xff0c;给大家详细的唠叨一下mfc140u.dll丢失的各种解决方法&#xff0c;教大家以最快最有效率的方法去解决mfc140u.…

Low Memory Killer in Android

目录 低内存管理&#xff08;Linux vs Android&#xff09; Linux内存回收 shrink_slab原理 shrink_zone原理 oom killer oom killer设计原则 OOM killer具体实现 android的lmk(Low Memory Killer) Android系统特点 oom killer在android中的不足 ​​​​​​​LMK概…

探索 Python 的 vars() 函数

大家好&#xff0c;在软件开发的过程中&#xff0c;调试是一个不可或缺的环节。无论你是在解决 bug&#xff0c;优化代码&#xff0c;还是探索代码的执行流程&#xff0c;都需要一些有效的工具来帮助你更好地理解和调试代码。在 Python 编程中&#xff0c;vars() 函数是一个非常…

国产可视化爬虫助力AI大模型训练:精准爬取汉语词典

大语言模型&#xff0c;可以生成流畅对话的会话聊天机器人、通畅起草文章的内容生成器。在炫酷技术的背后&#xff0c;数据、算力、算法&#xff0c;被视作生成式AI的三个核心要素。由此可见&#xff0c;高质量的训练数据对于AI算法的准确性至关重要。 如何获得高质量的训练数…

【嵌入式硬件】DRV8874电机驱动

目录 1 芯片介绍 1.1 特性简介 1.2 引脚配置 1.3 最佳运行条件 2 详细说明 2.1 PMODE配置控制模式 2.1.1 PH/EN 控制模式 2.1.2 PWM 控制模式 2.1.3 独立半桥控制模式 2.2 电流感测和调节 2.2.1 IPROPI电流感测 2.2.2 IMODE电流调节 3.应用 3.1设计要求 3.2 设计…

数据结构严蔚敏版精简版-绪论

1.基本概念和术语 下列概念和术语将在以后各章节中多次出现&#xff0c;本节先对这些概念和术语赋予确定的含义。 数据(Data)&#xff1a;数据是客观事物的符号表示&#xff0c;是所有能输入到计算机中并被计算机程序处理的符号 的总称。 数据元素(DataElement)&#xff1a;…

JVM运行时数据区 - 程序计数器

运行时数据区 Java虚拟机在执行Java程序的过程中&#xff0c;会把它管理的内存划分成若干个不同的区域&#xff0c;这些区域有各自的用途、创建及销毁时间&#xff0c;有些区域随着虚拟机的启动一直存在&#xff0c;有些区域则随着用户线程的启动和结束而建立和销毁&#xff0…

JAVAEE1

Web前端&#xff1a; 1.建立web开发的息维模式写代码不仅仅是为了实现某个功能&#xff0c;更是学习解决问题的思维方式 2.先使用&#xff0c;再理解&#xff0c;会导致刚开始比较懵&#xff0c;不知其所以然.切忌不可深陷其中&#xff0c; 3.涉及简单的软件工程的设计思想&…

Java Agent利器

一、JavaAgent技术 1.1 什么是JavaAgent JavaAgent是一种特殊的Java程序&#xff0c;是Instrumentation的客户端。它与普通Java程序通过main方法启动不同&#xff0c;JavaAgent并不是一个可以单独启动的程序&#xff0c;它必须依附在一个Java应用程序&#xff08;JVM&#xf…

Spring创建对象的多种方式

一、对象分类 简单对象&#xff1a;使用new Obj()方式创建的对象 复杂对象&#xff1a;无法使用new Obj()方式创建的对象。例如&#xff1a; 1. AOP创建代理对象。ProxyFactoryBean; 2. Mybatis中的SqlSessionFactoryBean; 3. Hibernate中的SessionFactoryBean。二、创建对象方…

Docker学习笔记 - 创建自己的image

目录 基本概念常用命令使用docker compose启动脚本创建自己的image 使用Docker是现在最为流行的软件发布方式&#xff0c; 本系列将阐述Docker的基本概念&#xff0c;常用命令&#xff0c;启动脚本和如何生产自己的docker image。 在我们发布软件时&#xff0c;往往需要把我…

Visual Studio Installer 点击闪退

Visual Studio Installer 点击闪退问题 1. 问题描述2. 错误类型3. 解决方法4. 结果5. 说明6. 参考 1. 问题描述 重装了系统后&#xff08;系统版本&#xff1a;如下图所示&#xff09;&#xff0c;我从官方网站&#xff08;https://visualstudio.microsoft.com/ ) 下载了安装程…

OpenAI 推出ChatGPT Edu,为高校定制版本

近日&#xff0c;OpenAI 宣布推出 ChatGPT Edu&#xff0c;这是一款专为高校打造的 ChatGPT 版本&#xff0c;旨在帮助学生、教师、研究人员和校园运营部门以负责任的方式部署和使用 AI。 ChatGPT Edu 由 GPT-4o 提供支持&#xff0c;具备强大的文本和图像推理能力&#xff0c;…

FS212E 系列PD协议

PD快充协议芯片FS212EL、FS212EH可以智能的识别插入的手机类型&#xff0c;选择最为合适的协议应对手机快充需要。兼容多类USB Type-C协议&#xff0c;包括TypeC协议、TypeC PD2.0、TypeC PD3.0、TypeC PD3.2等协议。集成OPTO输出&#xff0c;通过电阻直驱反馈光耦。FS212E 的调…

hexo init命令报错:Error: EPERM: operation not permitted, mkdir ‘D:\‘

我用的是git bash通过hexo init安装hexo的&#xff0c;但是报错如下&#xff1a; $ hexo init INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git fatal: unable to access https://github.com/hexojs/hexo-starter.git/: HTTP/2 stream 1 was not clos…

Firebase Local Emulator Suite详解

文章目录 Firebase Local Emulator Suite 组件安装和使用步骤1. 安装 Firebase CLI2. 初始化 Firebase 项目3. 配置模拟器4. 启动模拟器5. 配置应用程序使用本地模拟器 常见用途 Firebase Local Emulator Suite 是一组本地服务&#xff0c;可以模拟 Firebase 平台的在线服务&am…

以sqlilabs靶场为例,讲解SQL注入攻击原理【25-31关】

【Less-25】 首先分析源码 发现把 SQL语句中的 or、and 替换成了空格&#xff0c;这就导致无法使用之前的sql注入方式。 解决方案&#xff1a;用 && 代替 and &#xff0c; 用 || 代替 or &#xff0c; 而且&在url中有特殊含义&#xff0c;如果直接使用会有问题&a…