Создание базовых профилей

Автоматически генерируйте профили для каждого выпуска приложения с помощью библиотеки Jetpack Macrobenchmark и BaselineProfileRule . Мы рекомендуем использовать com.android.tools.build:gradle:8.0.0 или более позднюю версию, которая включает улучшения сборки при использовании Baseline Profiles.

Ниже приведены общие шаги по созданию нового базового профиля:

  1. Настройте модуль базового профиля.
  2. Определите тест JUnit, который поможет генерировать базовые профили.
  3. Добавьте критические пользовательские маршруты (CUJ), которые вы хотите оптимизировать.
  4. Создайте базовый профиль.

После создания базового профиля протестируйте его с помощью физического устройства, чтобы измерить улучшения скорости.

Создайте новый базовый профиль с AGP 8.2 или выше

Самый простой способ создать новый базовый профиль — использовать шаблон модуля «Базовый профиль», доступный начиная с Android Studio Iguana и Android Gradle Plugin (AGP) 8.2.

Шаблон модуля «Генератор базовых профилей» для Android Studio автоматизирует создание нового модуля для генерации и тестирования базовых профилей. При запуске шаблона генерируется большая часть типовой конфигурации сборки, генерации базовых профилей и кода проверки. Шаблон создаёт код для генерации и тестирования базовых профилей для измерения скорости запуска приложения.

Настройка модуля базового профиля

Чтобы запустить шаблон модуля «Базовый профиль», выполните следующие действия:

  1. Выберите Файл > Создать > Новый модуль.
  2. Выберите шаблон «Генератор базовых профилей» на панели «Шаблоны» и настройте его:
    Рисунок 1. Шаблон модуля генератора базовых профилей.

    Поля в шаблоне следующие:

    • Целевое приложение : определяет, для какого приложения генерируется базовый профиль. Если в проекте только один модуль приложения, в этом списке будет только один элемент.
    • Имя модуля : имя, которое вы хотите присвоить создаваемому модулю базового профиля.
    • Имя пакета : имя пакета, которое вы хотите указать для модуля Baseline Profile.
    • Язык : хотите ли вы, чтобы сгенерированный код был на Kotlin или Java.
    • Язык конфигурации сборки : хотите ли вы использовать Kotlin Script (KTS) или Groovy для своих скриптов конфигурации сборки.
    • Используйте устройство, управляемое Gradle : используете ли вы устройства, управляемые Gradle, для тестирования своего приложения.
  3. Нажмите «Готово» , и новый модуль будет создан. Если вы используете систему управления версиями, вам может быть предложено добавить файлы новых модулей в систему управления версиями.

Определить генератор базового профиля

Новый модуль содержит тесты для генерации и оценки базового профиля, а также для тестирования только базового запуска приложения. Мы рекомендуем расширить их, включив CUJ и расширенные рабочие процессы запуска. Убедитесь, что все тесты, связанные с запуском приложения, находятся в блоке rule с параметром includeInStartupProfile , установленным в значение true ; и наоборот, для оптимальной производительности убедитесь, что все тесты, не связанные с запуском приложения, не включены в профиль запуска. Оптимизация запуска приложения используется для определения специальной части базового профиля, называемой профилем запуска .

Абстрагирование этих CUJ-файлов от сгенерированного базового профиля и кода бенчмарка повышает удобство поддержки. Это означает, что изменения в ваших CUJ-файлах будут применяться согласованно.

Создайте и установите базовый профиль

Шаблон модуля «Базовый профиль» добавляет новую конфигурацию запуска для генерации базового профиля. При использовании различных вариантов продукта Android Studio создаёт несколько конфигураций запуска, чтобы вы могли создавать отдельные базовые профили для каждого варианта.

Конфигурация запуска Генерации базового профиля.
Рисунок 2. Запуск этой конфигурации генерирует базовый профиль.

После завершения конфигурации запуска Generate Baseline Profile сгенерированный базовый профиль копируется в файл src/ variant /generated/baselineProfiles/baseline-prof.txt в профилируемом модуле. Вариантами могут быть либо сборка типа release, либо вариант сборки, включающий сборку типа release.

Сгенерированный базовый профиль изначально создаётся в build/outputs . Полный путь определяется вариантом или разновидностью профилируемого приложения, а также тем, используете ли вы для профилирования устройство под управлением Gradle или подключённое устройство. Если вы используете имена, используемые в коде и конфигурациях сборки, сгенерированных шаблоном, базовый профиль создаётся в файле build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt . Вам, вероятно, не придётся взаимодействовать с этой версией сгенерированного базового профиля напрямую, если только вы не копируете его вручную в целевые модули (не рекомендуется).

Создайте новый базовый профиль с помощью AGP 8.1

Если вы не можете использовать шаблон модуля Baseline Profile , создайте новый Baseline Profile с помощью шаблона модуля Macrobenchmark и плагина Gradle Baseline Profile. Мы рекомендуем использовать эти инструменты, начиная с Android Studio Giraffe и AGP 8.1.

Ниже приведены шаги по созданию нового базового профиля с использованием шаблона модуля Macrobenchmark и плагина Baseline Profile Gradle:

  1. Настройте модуль Macrobenchmark в своем проекте Gradle.
  2. Определите новый класс с именем BaselineProfileGenerator :
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }

    Генератор может включать в себя взаимодействие с вашим приложением за пределами его запуска. Это позволяет оптимизировать производительность приложения во время выполнения, например, прокрутку списков, запуск анимации и навигацию внутри Activity . Ознакомьтесь с другими примерами тестов, использующих @BaselineProfileRule для улучшения критически важных действий пользователя.

  3. Добавьте плагин Gradle Baseline Profile ( libs.plugins.androidx.baselineprofile ). Этот плагин упрощает создание базовых профилей и их поддержку в будущем.

  4. Чтобы сгенерировать базовый профиль, запустите задачи Gradle :app:generateBaselineProfile или :app:generate Variant BaselineProfile в терминале.

    Запустите генератор в качестве инструментированного теста на физическом устройстве с root-доступом, эмуляторе или устройстве Gradle Managed Device . Если вы используете устройство Gradle Managed Device, установите aosp в качестве systemImageSource , так как для генератора базового профиля вам потребуется root-доступ.

    По завершении задачи генерации базовый профиль копируется в app/src/ variant /generated/baselineProfiles .

Создайте новый базовый профиль без шаблонов

Мы рекомендуем создавать базовый профиль с помощью шаблона модуля Android Studio Baseline Profile (предпочтительно) или шаблона Macrobenchmark , но вы также можете использовать плагин Baseline Profile Gradle. Подробнее о плагине Baseline Profile Gradle см. в статье «Настройка генерации базового профиля» .

Вот как создать базовый профиль, используя плагин Baseline Profile Gradle напрямую:

  1. Создайте новый модуль com.android.test , например, :baseline-profile .
  2. Настройте файл build.gradle.kts для :baseline-profile :

    1. Примените плагин androidx.baselineprofile .
    2. Убедитесь, что targetProjectPath указывает на модуль :app .
    3. При желании добавьте устройство, управляемое Gradle (GMD) . В следующем примере это pixel6Api31 . Если не указано иное, плагин использует подключенное устройство, эмулированное или физическое.
    4. Примените нужную конфигурацию, как показано в следующем примере.

    Котлин

    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
    }

    Круто

    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 . Следующий пример — тест, который запускает приложение и ожидает перехода в режим ожидания.

    Котлин

    class BaselineProfileGenerator {
    
        @get:Rule
        val baselineRule = BaselineProfileRule()
    
        @Test
        fun startupBaselineProfile() {
            baselineRule.collect("com.myapp") {
                startActivityAndWait()
            }
        }
    }

    Ява

    public class BaselineProfileGenerator {
    
        @Rule
        Public BaselineProfileRule baselineRule = new BaselineProfileRule();
    
        @Test
        Public void startupBaselineProfile() {
            baselineRule.collect(
                "com.myapp",
                (scope -> {
                    scope.startActivityAndWait();
                    Return Unit.INSTANCE;
                })
            )
        }
    }
  4. Обновите файл build.gradle.kts в модуле app, например :app .

    1. Примените плагин androidx.baselineprofile .
    2. Добавьте зависимость baselineProfile к модулю :baseline-profile .

    Котлин

    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"))
    }

    Круто

    plugins {
        id 'com.android.application'
        id 'androidx.baselineprofile'
    }
    
    android {
        // No changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile ':baseline-profile'
    }
  5. Создайте профиль, выполнив задачи Gradle :app:generateBaselineProfile или :app:generate Variant BaselineProfile .

  6. По завершении задачи генерации базовый профиль копируется в app/src/ variant /generated/baselineProfiles .

Создайте новый базовый профиль с AGP 7.3-7.4

Можно создавать базовые профили с помощью AGP 7.3-7.4, но мы настоятельно рекомендуем выполнить обновление как минимум до AGP 8.1, чтобы вы могли использовать плагин Gradle Baseline Profile и его новейшие функции.

Если вам необходимо создать базовые профили с AGP 7.3-7.4, шаги будут такими же, как и для AGP 8.1 , за следующими исключениями:

Применяйте созданные правила вручную

Генератор базового профиля создаёт текстовый файл в формате HRF (Human Readable Format) на устройстве и копирует его на хост-компьютер. Чтобы применить сгенерированный профиль к вашему коду, выполните следующие действия:

  1. Найдите файл 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/main/ и переименуйте файл в baseline-prof.txt .

  3. Добавьте зависимость к библиотеке ProfileInstaller в файл build.gradle.kts вашего приложения, чтобы включить локальную компиляцию базового профиля там, где облачные профили недоступны. Это единственный способ локально загрузить базовый профиль.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.4.1")
    }
    
  4. Создайте рабочую версию приложения, пока применяемые правила HRF компилируются в двоичный формат и включаются в APK или AAB. Затем распространяйте приложение как обычно.

Сравнительный анализ базового профиля

Чтобы протестировать базовый профиль, создайте новую конфигурацию Android Instrumented Test Run из действия Gutter, которое выполняет тесты, определённые в файле StartupBenchmarks.kt или StartupBencharks.java . Подробнее о тестировании производительности см. в разделах Создание класса Macrobenchmark и Автоматизация измерений с помощью библиотеки Macrobenchmark .

Рисунок 3. Запуск тестов Android из действия «Корзина».

При запуске этого кода в Android Studio выходные данные сборки содержат подробную информацию об улучшениях скорости, которые обеспечивает базовый профиль:

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 плюс время отображения контента, который загружается асинхронно после отображения начального кадра.

TTFD сообщается после вызова метода reportFullyDrawn() объекта ComponentActivity . Если reportFullyDrawn() не вызывается, вместо него сообщается TTID. Возможно, потребуется отложить вызов reportFullyDrawn() до завершения асинхронной загрузки. Например, если пользовательский интерфейс содержит динамический список, такой как RecyclerView или lazy list , этот список может быть заполнен фоновой задачей, которая завершается после первой отрисовки списка и, следовательно, после того, как пользовательский интерфейс будет помечен как полностью отрисованный. В таких случаях код, выполняемый после того, как пользовательский интерфейс достигнет состояния полной отрисовки, не включается в базовый профиль.

Чтобы включить заполнение списка в базовый профиль, получите FullyDrawnReporter с помощью getFullyDrawnReporter() и добавьте к нему репортёр в код приложения. Освободите репортёр после того, как фоновая задача завершит заполнение списка. FullyDrawnReporter не вызывает метод reportFullyDrawn() пока не будут освобождены все репортёры. Благодаря этому базовый профиль включает в себя пути кода, необходимые для заполнения списка. Это не меняет поведение приложения для пользователя, но позволяет базовому профилю включать все необходимые пути кода.

Если ваше приложение использует Jetpack Compose , используйте следующие API для указания полностью отрисованного состояния:

  • ReportDrawn указывает на то, что ваш компонуемый объект сразу готов к взаимодействию.
  • ReportDrawnWhen принимает предикат, например list.count > 0 , чтобы указать, когда ваш компонуемый объект готов к взаимодействию.
  • ReportDrawnAfter принимает метод приостановки, который по завершении указывает, что ваш компонуемый объект готов к взаимодействию.
{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}