安卓启动 性能提升 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.ManagedVirtualDevice


android {

.......................
.......................
 targetProjectPath = ":app"
 testOptions.managedDevices.devices {
        create<ManagedVirtualDevice>("pixel6Api31") {
            device = "Pixel 6"
            apiLevel = 31
            systemImageSource = "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,就演示一下,代码如下

  @Test
    fun 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-optimizations
            includeInStartupProfile = 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 app
            pressHome()
            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.size
        snacks[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_17
    targetCompatibility = 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 = 28
    targetSdk = 34

    testInstrumentationRunner = "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.size
        snacks[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多,到这里教程就结束了,谢谢大家

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Algorithm][动态规划][子序列问题][最长递增子序列的个数][最长数对链]详细讲解

目录 1.最长递增子序列的个数1.题目链接2.算法原理详解3.代码实现 2.最长数对链1.题目链接2.算法原理详解3.代码实现 1.最长递增子序列的个数 1.题目链接 最长递增子序列的个数 2.算法原理详解 注意&#xff1a;本题思路和思维方式及用到的方法很值得考究&#xff0c;个人感…

GPT4o还没用上?落后一个月!

文章目录 一.Share官方网站&#xff1a;以一半的价格享受官网服务1.1 网址1.2 一些介绍和教学实战&#xff1a;1.3 主界面&#xff08;支持4o)&#xff1a;1.4 GPTS&#xff08;上千个工具箱任你选择&#xff09;&#xff1a;1.5 快速的文件数据分析&#xff08;以数学建模为例…

CPU/GPU/FPSGO,负载调试/设置命令开关

CPU/GPU/FPSGO&#xff0c;负载调试/设置命令开关 首先&#xff0c;进入&#xff1a; adb shell cat sys/kernel/ged/hal/gpu_utilization 查看GPU的负载情况。输出三个数字&#xff0c;第1个表示使用率&#xff0c;第3个表示空闲率。 echo 0 /sys/kernel/fpsgo/common/force…

Tableau创建数据提取

Tableau创建数据提取通过与原始数据集分离可有效减少总体数据量。以下通过示例-超市数据进行演示&#xff1a; 需求&#xff1a;提取华北及东北地区家具销售利润低于5000的数据 1&#xff09; 连接到数据并在“数据源”页面上设置数据源后&#xff0c;请在右上角选择“数据提…

Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明

Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明 目录 Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明 一、简单介绍 二、处理文本数据 三、用…

Java中的软引用,你了解吗?

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

关系数据库:关系运算

文章目录 关系运算并&#xff08;Union&#xff09;差&#xff08;Difference&#xff09;交&#xff08;Intersection&#xff09;笛卡尔积&#xff08;Extended Cartesian Product&#xff09;投影&#xff08;projection&#xff09;选择&#xff08;Selection&#xff09;除…

翻译《The Old New Thing》- What a drag: Dragging a virtual file (IStream edition)

What a drag: Dragging a virtual file (IStream edition) - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080319-00/?p23073 Raymond Chen 2008年03月19日 拖拽虚拟文件&#xff08;IStream 版本&#xff09; 上一次&#xff0c;我们看…

Scikit-Learn 基础教程

目录 &#x1f40b;Scikit-Learn 基础教程 &#x1f40b;Scikit-Learn 简介 &#x1f40b; 数据预处理 &#x1f988;数据集导入 &#x1f988;数据清洗 &#x1f988;特征选择 &#x1f988;特征标准化 &#x1f40b; 模型选择 &#x1f988;分类模型 &#x1f988;回…

【 0 基础 Docker 极速入门】镜像、容器、常用命令总结

Docker Images&#xff08;镜像&#xff09;生命周期 Docker 是一个用于创建、部署和运行应用容器的平台。为了更好地理解 Docker 的生命周期&#xff0c;以下是相关概念的介绍&#xff0c;并说明它们如何相互关联&#xff1a; Docker&#xff1a; Docker 是一个开源平台&#…

HTML旋转照片盒子

效果图 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" content…

docker私有镜像仓库的搭建及认证

简介&#xff1a; docker私有镜像仓库的搭建及认证 前言 在生产上使用的 Docker 镜像可能包含我们的代码、配置信息等&#xff0c;不想被外部人员获取&#xff0c;只允许内 网的开发人员下载。 Docker 官方提供了一个叫做 registry 的镜像用于搭建本地私有仓库使用。在内部网…

C 基础 - 预处理命令和基本语法详解

#include <stdio.h> //预处理指令int main() //函数 {printf("Hello, World!"); //输出语句return 0; //返回语句 } 目录 一.预处理指令 1.#define #ifdef #ifndef #if #else #elif #endif 2.#inlcude a.新增一个文件 b.#include c.运行结果 d.扩…

Liunx中使用他人身份来执行命令或新建文件

前言 在一些情况下。我们想要借助某个用户的身份来执行命令或者新建文件&#xff0c; 比如某个用户的bash是 nologin 或者 false。 该怎么做呢&#xff1f;&#xff1f; 答&#xff1a;使用 sudo -u 即可。 例如&#xff1a; sudo -u ygz1 touch temp1.txt哈哈哈&#xff0…

【FPGA】Verilog语言从零到精通

接触fpga一段时间&#xff0c;也能写点跑点吧……试试系统地康康呢~这个需要耐心但是回报巨大的工作。正原子&&小梅哥 15_语法篇&#xff1a;Verilog高级知识点_哔哩哔哩_bilibili 1Verilog基础 Verilog程序框架&#xff1a;模块的结构 类比&#xff1a;c语言的基础…

javascript DOM 属性详解:读取、修改、移除

No.内容链接1Openlayers 【入门教程】 - 【源代码示例300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3Cesium 【入门教程】 - 【源代码图文示例200】 4MapboxGL【入门教程】 - 【源代码图文示例150】 5前端就业宝典 【面试题详细答案 1000】 文章目录 一、读取…

Tesseract-OCR使用 jTessBoxEditor 进行训练及python调用

Python-tesseract 是 python 的光学字符识别 &#xff08;OCR&#xff09; 工具。 也就是说&#xff0c;它将识别并“读取”嵌入在图像中的文本。 1、下载安装 jTessBoxEditor和tesseract-ocr 我下载的是jTessBoxEditor-2.2.0版本的&#xff0c;里面自带tesseract-ocr。 两种…

哪款桌面便签软件安全好用?2024好用便签app推荐

桌面便签软件已经成为许多人日常生活和工作中不可或缺的工具&#xff0c;它们实用、灵活&#xff0c;能够帮助我们快速记录重要信息&#xff0c;提醒任务事项。随着科技的进步&#xff0c;市面上的便签软件层出不穷&#xff0c;功能也越发强大和实用。在众多的便签软件中&#…

Linux网络-使用Tcp协议进行网络通信并通过网络接口实现远端翻译

文章目录 Tcp协议Tcp协议常见API接口1. int socket(int domain, int type, int protocol);2. int bind(int socket, const struct sockaddr *address, socklen_t address_len);struct sockaddr 3. int listen(int socket, int backlog);4. int accept(int socket, struct socka…

[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle

前言 今天给大家分享一个方便易用的.NET在线代码编辑工具&#xff0c;能够帮助.NET开发人员快速完成代码编写、测试和分享的需求&#xff08;.NET开发者的福音&#xff09;&#xff1a;.NET Fiddle。 .NET Fiddle介绍 我们可以不用再担心环境与庞大的IDE安装的问题&#xff0…