安卓启动 性能提升 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多,到这里教程就结束了,谢谢大家
相关文章:
安卓启动 性能提升 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)设备运行&a…...
Linux C/C++目录和文件的更多操作
1.access()库函数 用于判断当前用户对目录或文件的存取权限 #include<unistd.h>int accsee(const char *pathname,int mode);参数说明: pathname //目录或文件名 mode //需要判断的存取权限,在<unistd.h>预定义如下#define R_OK 4 //读权…...
如何高效地向Redis 6插入亿级别的数据
如何高效地向Redis插入亿级别的数据 背景不可用的方案可用方案:利用管道插入其他命令:参考: 背景 上一条记录;80G的存储;10几个文件,如何快速导入是一个大问题,也是一个很棘手的问题;如下将给出…...
中国历年肥料进口数量统计报告
数据来源于国家统计局,为1991年到2021年我国每年肥料进口数量统计。 2021年,我国进口肥料909万吨,比上年减少151万吨。 数据统计单位为:万吨 数据说明: 数据来源于国家统计局,为海关进出口统计数 我国肥料…...
即时通讯视频会议平台,WorkPlus本地化部署解决方案
随着现代科技的快速发展,传统的会议方式已经不再满足企业和组织的需求。即时通讯视频会议以其便利性和高效性,成为了现代企业沟通和协作的重要工具。通过即时通讯视频会议,企业可以实现无时差的交流和远程协作,增强团队合作和提高…...
Java的数据库编程-----JDBC
目录 一.JDBC概念&使用条件: 二.mysql-connector驱动包的下载与导入: 三.JDBC编程: 使用JDBC编程的主要五个步骤: 完整流程1(更新update): 完整流程2(查询query): 一.JDB…...
如何获取SSL证书,消除网站不安全警告
获取SSL证书通常涉及以下几个步骤: 选择证书颁发机构(CA): 你需要从受信任的SSL证书颁发机构中选择一个,比如DigiCert、GlobalSign、JoySSL等。部分云服务商如阿里云、腾讯云也提供免费或付费的SSL证书服务。 生成证…...
Unity动画系统介绍
Unity动画系统介绍 Animator组件: 这是Unity中用于控制动画状态的组件,它与Animator Controller一起工作,可以基于游戏逻辑来切换不同的动画状态。 Animator Controller: 这是一个用于管理动画状态机的组件,它允许…...
Three.js-实现加载图片并旋转
1.实现效果 2. 实现步骤 2.1创建场景 const scene new THREE.Scene(); 2.2添加相机 说明: fov(视场角):视场角决定了相机的视野范围,即相机可以看到的角度范围。较大的视场角表示更广阔的视野,但可能…...
ACM实训第25天
第四套 第一道(修改) #include<stdio.h> #include<string.h> int cnt[10]; void count_digits(int n,int* cnt){for(int i1;i<n;i){int numi;while(num){cnt[num%10];num/10;}} } int main(){int t;scanf("%d\n",&t);whi…...
GraphQL(2):使用express和GraphQL编写helloworld
1 安装express、graphql以及express-graphql 在项目的目录下运行一下命令。 npm init -y npm install express graphql express-graphql -S 2 新建helloworld.js 代码如下: const express require(express); const {buildSchema} require(graphql); const grap…...
Vue中的计算属性和侦听器:提升响应式编程的艺术
引言 Vue.js是一个用于构建用户界面的渐进式框架,它的核心特性之一是响应式编程。Vue通过数据绑定和响应式系统,使得开发者能够以声明式的方式处理数据变化。在Vue中,计算属性(Computed Properties)和侦听器ÿ…...
JavaScript倍速播放视频
F12打开开发者工具,打开控制台,输入这行代码,视频即可加速播放, 可以调整倍速(2,4,8,16) document. getElementsByTagName("video")[0]. playbackRate16...
ER图介绍
在数据库设计和建模中,实体-关系图(Entity-Relationship Diagram,简称ER图)是一个至关重要的工具。ER图通过图形化的方式描述了现实世界中的实体(Entity)及其之间的关系(Relationship࿰…...
Oracle通过datax迁移线上表到历史库
历史数据迁移 线上库数据增长迅速,需要定期清理历史数据,因为异地灾备,但是带宽很小,不能使用数据泵直接往历史库导数,会导致本地机房到灾备机房的带宽被占满,调研过flink、golden gate、datax,…...
java基础-深拷贝和浅拷贝
java中有一个概念叫深拷贝和浅拷贝,那这两个是什么意思呢?其实你可以对比一下c中的传值和传引用的问题。 深拷贝 即两个相同的对象地址不同,比如对象A通过拷贝出来对象B,在对B对象进行操作时不会影响到A对象的内容。 浅拷贝 和…...
Java数组操作
数组拓展 1.1 数组拷贝 需求:定义一个方法arraycopy, 从指定源数组中从指定的位置开始复制指定数量的元素到目标数组的指定位置。 1.2. 排序操作 需求:完成对int[] arr new int[]{2,9,6,7,4,1}数组元素的升序排序操作. 1.2.1.冒泡排序 对未排序的各元素…...
C++vector及其实现
第一个参数是类型(可以是自定义也可以是内置类型) 相当于生成一个该类型的数组 allocator是空间配置器 遍历 1.下标遍历 2.迭代器遍历 3.范围for 对象访问 有名对象访问 匿名对象访问 隐式类型转换 成员函数 sort 使用sort需要包含头文件algorithm eg. sort的使用非…...
路由策略实验1
先把地址全部配通 对R1 对R2 对R4 对R3 对R5 对R6 对R7 然后起路由协议 对R1 对R2 对R3 对R4 对R5 对R6 对R7...
含情脉脉的进程
冯诺依曼体系结构 一个计算机在工作的时候是怎样的呢? 我们所认识的计算机都是由一个个的硬件组件组成: 输入设备:键盘、鼠标、摄像头、话筒、磁盘、网卡 中央处理器(CPU):运算器、控制器 输出设备&#x…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
