Android NDK开发详解之调试和性能分析的创建基准配置文件

使用 Jetpack Macrobenchmark 库和 BaselineProfileRule 为每个应用版本自动生成配置文件。我们建议您使用 com.android.tools.build:gradle:8.1.0 或更高版本,因为这些版本改进了使用基准配置文件时的构建功能。

以下是创建新基准配置文件的一般步骤:

1、设置基准配置文件模块。
2、定义有助于生成基准配置文件的 JUnit 测试。
3、添加您想要优化的关键用户历程 (CUJ)。
4、生成基准配置文件。

生成基准配置文件后,使用实体设备对其进行基准测试以测量速度改进。

使用 AGP 8.2 或更高版本创建新的基准配置文件

创建新的基准配置文件的最简单方式是使用基准配置文件模块模板,该模板从 Android Studio Iguana 和 Android Gradle Plugin (AGP) 8.2 开始提供。
实验性:基准配置文件模块功能目前在 Android Studio 预览版中提供。

Android Studio 基准配置文件生成器模块模板会自动创建一个新模块,以便生成基准配置文件并对其进行基准测试。运行该模板会生成大部分典型的 build 配置代码、基准配置文件生成代码,以及验证代码。该模板会创建用于生成基准配置文件并对其进行基准测试的代码,以便衡量应用启动情况。

设置基准配置文件模块

如需运行基准配置文件模块模板,请按以下步骤操作:

1、依次选择 File > New > New Module
2、在 Templates 面板中选择 Baseline Profile Generator 模板,并对其进行配置:
在这里插入图片描述

图 1. 基准配置文件生成器模块模板。

该模板中的字段如下:
    Target application:定义为哪个应用生成基准配置文件。如果项目中只有一个应用模块,此列表中将只有一项。
    Module name:您希望要创建的基准配置文件模块使用的名称。
    Package name:您希望基准配置文件模块使用的软件包名称。
    Language:您希望生成的代码是 Kotlin 还是 Java。
    Build configuration language:您希望 build 配置脚本使用 Kotlin Script (KTS) 还是 Groovy。
3、点击 Finish,即会创建一个新模块。如果您使用源代码控制工具,系统可能会提示您将新创建的模块文件添加到源代码控制工具中。

定义基准配置文件生成器

新创建的模块中包含用于生成基准配置文件并对其进行基准测试的测试,以及用于仅测试基本应用启动时间的测试。我们建议您将这些代码扩充为包含 CUJ 和高级启动工作流。如果您将这些 CUJ 提取到生成的基准配置文件和基准测试代码之外,以便它们可以用于这两者,将有助于提高可维护性。这意味着会一致地使用您对 CUJ 所做的更改。

如需了解要添加的 CUJ 的示例,请参阅示例 BaselineProfileGenerator.kt 文件。

生成并安装基准配置文件

基准配置文件模块模板中添加了一个新的运行配置,用于生成基准配置文件:如果您使用产品变种,Android Studio 会创建多个运行配置,以便您可以为每个变种生成单独的基准配置文件。
注意:要从命令行界面生成并安装基准配置文件,请运行 :app:generateBaselineProfile 或 :app:generateVariantBaselineProfile Gradle 任务。
在这里插入图片描述

图 2. 运行此配置会生成基准配置文件。

Generate Baseline Profile 运行配置在完成运行后,会将生成的基准配置文件复制到要分析的模块中的 src/variant/generated/baselineProfiles/baseline-prof.txt 文件。

生成的基准配置文件最初是在 build/outputs 中创建的。完整路径取决于要分析的应用变体或变种,以及您是使用 Gradle 管理的设备还是使用已连接的设备进行分析。如果您使用代码所用的名称和由模板生成的 build 配置,系统会在 build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt 文件中创建基准配置文件。您可能不必直接与此版本的生成的基准配置文件交互,除非您手动将其复制到目标模块(不推荐)。

使用 AGP 8.1 创建新的基准配置文件

如果您无法使用基准配置文件模块模板,请使用 Macrobenchmark 模块模板和基准配置文件 Gradle 插件来创建新的基准配置文件。我们建议您针对 Android Studio Giraffe 和 AGP 8.1 以上版本使用这些工具。
注意:从 AGP 8.0 开始,可以使用 Baseline Profile Gradle 插件自动生成基准配置文件,但我们建议使用 AGP 8.1 以获享更好的体验。

以下是使用 Macrobenchmark 模块模板和 Baseline Profile Gradle 插件创建新的基准配置文件的步骤:

1、在 Gradle 项目中设置一个 Macrobenchmark 模块。
2、定义一个名为 BaselineProfileGenerator 的新类:
        class BaselineProfileGenerator {
         @get:Rule
            val baselineProfileRule = BaselineProfileRule()

            @Test
            fun startup() = baselineProfileRule.collect(
                packageName = "com.example.app",
                profileBlock = {
                    startActivityAndWait()
                }
            )
        }

该生成器可以包含应用启动之外的应用互动。这样,您就可以优化应用的运行时性能,例如滚动列表、运行动画、在 Activity 内导航等等。您可以查看其他的测试示例,了解如何使用 @BaselineProfileRule 改善关键用户历程。
3、生成基准配置文件时,关闭混淆功能。为此,您只需要为负责生成配置文件的 benchmark build 类型执行以下操作即可:在应用模块中再创建一个 ProGuard 文件,并添加 -dontobfuscate。
注意:只有生成基准配置文件时才需要未经混淆处理的 build。您的正式版应用可采用混淆处理。
Kotlin

buildTypes {
    val benchmark by creating {
        // Only use benchmark Proguard rules.
        proguardFiles("benchmark-rules.pro")
        // ...
    }
}

Groovy

 buildTypes {
        val benchmark by creating {
            // Only use benchmark Proguard rules.
            proguardFiles("benchmark-rules.pro")
            // ...
        }
    }

4、添加基准配置文件 Gradle 插件 (libs.plugins.androidx.baselineprofile)。该插件可以更轻松地生成基准配置文件并在将来维护它们。

5、要生成基准配置文件,请在终端中运行 :app:generateBaselineProfile 或 :app:generateVariantBaselineProfile Gradle 任务。

在已启用 root 权限的实体设备、模拟器或 Gradle 管理的设备上,将生成器作为插桩测试运行。如果您使用 Gradle 管理的设备,请将 aosp 设置为 systemImageSource,因为您需要对基准配置文件生成器的 root 访问权限。
注意:使用 Jetpack Macrobenchmark 1.2.0-alpha06 及更高版本时,您可以在运行 Android 13 (API 33) 及更高版本的设备上生成基准配置文件,而无需 root 访问权限。

生成任务结束时,基准配置文件将复制到 app/src/release/generated/baselineProfiles。

不使用模板创建新的基准配置文件

我们建议使用 Android Studio Baseline Profile 模块模板(首选)或 Macrobenchmark 模板创建基准配置文件,但您也可以单独使用基准配置文件 Gradle 插件。要了解有关基准配置文件 Gradle 插件的更多信息,请参阅配置您的基准配置文件生成。
注意:如果您使用基准配置文件模块模板,则表示已经应用了基准配置文件 Gradle 插件。

以下是直接使用基准配置文件 Gradle 插件创建基准配置文件的方法:

1、创建一个新的 com.android.test 模块,例如 :baseline-profile。
2、为 :baseline-profile 配置 build.gradle.kts 文件:
    a、应用 androidx.baselineprofile 插件。
    b、确保 targetProjectPath 指向 :app 模块。
    c、(可选)添加 Gradle 管理的设备 (GMD)。 在以下示例中,它是 pixel6Api31。如果未指定,该插件将使用一部已连接的模拟或实体设备。
    d、应用您需要的配置,如以下示例所示。

Kotlin

plugins {
    id("com.android.test")
    id("androidx.baselineprofile")
}

android {

    defaultConfig {
        ...
    }

    // Point to the app module, the module that you're generating the Baseline Profile for.
    targetProjectPath = ":app"

    // Configure a GMD (optional).
    testOptions.managedDevices.devices {
        pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
            device = "Pixel 6"
            apiLevel = 31
            systemImageSource = "aosp"
        }
    }
}

dependencies { ... }

// Baseline Profile Gradle plugin configuration. Everything is optional. This
// example uses the GMD added earlier and disables connected devices.
baselineProfile {

    // Specifies the GMDs to run the tests on. The default is none.
    managedDevices += "pixel6Api31"

    // Enables using connected devices to generate profiles. The default is
    // `true`. When using connected devices, they must be rooted or API 33 and
    // higher.
    useConnectedDevices = false
}

Groovy

plugins {
    id("com.android.test")
    id("androidx.baselineprofile")
}

android {

    defaultConfig {
        ...
    }

    // Point to the app module, the module that you're generating the Baseline Profile for.
    targetProjectPath = ":app"

    // Configure a GMD (optional).
    testOptions.managedDevices.devices {
        pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
            device = "Pixel 6"
            apiLevel = 31
            systemImageSource = "aosp"
        }
    }
}

dependencies { ... }

// Baseline Profile Gradle plugin configuration. Everything is optional. This
// example uses the GMD added earlier and disables connected devices.
baselineProfile {

    // Specifies the GMDs to run the tests on. The default is none.
    managedDevices += "pixel6Api31"

    // Enables using connected devices to generate profiles. The default is
    // `true`. When using connected devices, they must be rooted or API 33 and
    // higher.
    useConnectedDevices = false
}

3、在 :baseline-profile 测试模块中创建基准配置文件测试。以下示例是一项会启动应用并等待应用进入空闲状态的测试。
Kotlin

class BaselineProfileGenerator {

    @get:Rule
    val baselineRule = BaselineProfileRule()

    @Test
    fun startupBaselineProfile() {
        baselineRule.collect("com.myapp") {
            startActivityAndWait()
        }
    }
}

Java

class BaselineProfileGenerator {

    @get:Rule
    val baselineRule = BaselineProfileRule()

    @Test
    fun startupBaselineProfile() {
        baselineRule.collect("com.myapp") {
            startActivityAndWait()
        }
    }
}

4、更新应用模块中的 build.gradle.kts 文件,例如 :app。

a、应用插件 androidx.baselineprofile。
b、将 baselineProfile 依赖项添加到 :baseline-profile 模块。

Kotlin

plugins {
    id("com.android.application")
    id("androidx.baselineprofile")
}

android {
    // There are no changes to the `android` block.
    ...
}

dependencies {
    ...
    // Add a `baselineProfile` dependency on the `:baseline-profile` module.
    baselineProfile(project(":baseline-profile"))
}

Groovy

plugins {
    id("com.android.application")
    id("androidx.baselineprofile")
}

android {
    // There are no changes to the `android` block.
    ...
}

dependencies {
    ...
    // Add a `baselineProfile` dependency on the `:baseline-profile` module.
    baselineProfile(project(":baseline-profile"))
}

5、通过运行 :app:generateBaselineProfile 或 :app:generateVariantBaselineProfile Gradle 任务生成配置文件。

生成任务结束时,基准配置文件将复制到 app/src/release/generated/baselineProfiles。

    </li>

使用 AGP 7.3-7.4 创建新的基准配置文件

您可以使用 AGP 7.3-7.4 生成基准配置文件,但我们强烈建议至少升级到 AGP 8.1,以便您可以使用基准配置文件 Gradle 插件及其最新功能。

如果您需要使用 AGP 7.3-7.4 创建基准配置文件,相应步骤与 AGP 8.1 的步骤相同,但以下情况例外:

不要添加基准配置文件 Gradle 插件。
要生成基准配置文件,请执行 Gradle 任务 ./gradlew [emulator name][flavor][build type]AndroidTest。例如 ./gradlew :benchmark:pixel6Api31BenchmarkAndroidTest。
您必须手动将生成的基准配置文件规则应用到您的代码。

手动应用生成的规则

基准配置文件生成器会在设备上创建一个人类可读格式 (HRF) 的文本文件,并会将其复制到宿主机中。若要将生成的配置文件应用于您的代码,请按照以下步骤操作:

1、在您生成配置文件时所用模块的 build 文件夹中找到 HRF 文件: [module]/build/outputs/managed_device_android_test_additional_output/[device]。

配置文件遵循 [class name]-[test method name]-baseline-prof.txt 命名模式,如下所示:BaselineProfileGenerator-startup-baseline-prof.txt。

2、对于任何给定变种,将生成的配置文件复制到应用模块中的 src/flavor/baselineProfiles。如需将配置文件应用于所有变种,请将其复制到 src/main/baselineProfiles。
注意:如果您使用的 Android Gradle 插件版本低于 8.0.0,请将基准配置文件复制到应用模块中的 src/main/,并将其重命名为 baseline-prof.txt。

3、在应用的 build.gradle.kts 文件中为 ProfileInstaller 库添加一个依赖项,以便在云配置文件不可用的情况下启用本地基准配置文件编译。这是在本地旁加载基准配置文件的唯一方式。
    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.3.1")
    }
4、构建应用的正式版,在此期间,所应用的 HRF 规则会被编译成二进制形式,并且会包含在 APK 或 AAB 中。然后,照常分发您的应用。

对基准配置文件进行基准测试

如需对基准配置文件进行基准测试,请通过负责执行 StartupBenchmarks.kt 或 StartupBencharks.java 文件中定义的基准测试的边线操作,创建新的 Android 插桩测试运行配置。如需详细了解基准测试,请参阅创建 Macrobenchmark 类和使用 Macrobenchmark 库自动进行衡量。
在这里插入图片描述

图 3. 通过边线操作运行 Android 测试。

当您在 Android Studio 中运行测试时,build 输出中会包含基准配置文件带来的速度提升的详细信息:

StartupBenchmarks_startupCompilationBaselineProfiles
timeToInitialDisplayMs   min 161.8,   median 178.9,   max 194.6
StartupBenchmarks_startupCompilationNone
timeToInitialDisplayMs   min 184.7,   median 196.9,   max 202.9

捕获所有必需的代码路径

衡量应用启动时间的两个关键指标如下:

初步显示所用时间 (TTID)
显示应用界面的第一帧所需的时间。
完全显示所用时间 (TTFD)
TTID 加上显示第一帧后显示异步加载的内容所用的时间。

系统会在调用 ComponentActivity 的 reportFullyDrawn() 方法后报告 TTFD。如果从未调用 reportFullyDrawn(),则改为报告 TTID。如果系统调用 reportFullyDrawn(),可能需要延迟到异步加载完成之后再报告相应时间。例如,如果界面包含一个动态列表(如 RecyclerView)或延迟列表,那么可能就要在首次绘制列表之后、因此也就是在界面被标记为完全绘制之后,才通过后台任务来填充该列表。在这种情况下,基准配置文件中将不包含在界面达到完全绘制状态后运行的代码。

如需将列表填充也纳入基准配置文件中,请使用 getFullyDrawnReporter() 获取 FullyDrawnReporter,并在应用代码中为其添加报告程序。一旦后台任务完成列表填充,便释放报告程序。在所有报告程序都被释放之后,FullyDrawnReporter 才会调用 reportFullyDrawn() 方法。这样一来,基准配置文件会包含填充列表所需的代码路径。这不会改变面向用户的应用行为,但可让基准配置文件包含所有必要的代码路径。

如果您的应用使用 Jetpack Compose,请使用以下 API 来指示完全绘制状态:

ReportDrawn 表示可组合项已准备好立即进行互动。
ReportDrawnWhen 接受一个谓词(例如 list.count > 0),以指明可组合项何时准备好进行互动。
ReportDrawnAfter 接受一个暂停方法,该方法完成即表示可组合项已准备好进行互动。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值