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

Базовые профили необходимы для максимальной производительности Jetpack Compose. Предварительная компиляция критически важных пользовательских сценариев помогает обеспечить плавную отрисовку пользовательского интерфейса Compose.

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

Вот общие шаги для создания нового базового профиля:

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

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

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

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

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

Настройка модуля «Базовый профиль»

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

  1. Выберите Файл > Создать > Новый модуль .
  2. Выберите шаблон «Генератор базового профиля» на панели «Шаблоны» и настройте его:
    Рисунок 1. Шаблон модуля «Генератор базового профиля».
    В шаблоне содержатся следующие поля:
    • Целевое приложение : приложение, для которого создается базовый профиль. Если в вашем проекте только один модуль приложения, в этом списке будет только один элемент.
    • Название модуля : имя, которое вы хотите присвоить создаваемому модулю «Базовый профиль».
    • Имя пакета : имя пакета, которое вы хотите использовать для модуля «Базовый профиль».
    • Язык : укажите, хотите ли вы, чтобы сгенерированный код был написан на Kotlin или Java.
    • Язык конфигурации сборки : хотите ли вы использовать Kotlin Script (KTS) или Groovy для скриптов конфигурации сборки.
    • Используйте управляемые Gradle устройства : указываете, используете ли вы управляемые Gradle устройства для тестирования вашего приложения.
  3. Нажмите «Готово» , и новый модуль будет создан. Если вы используете систему контроля версий, вам может быть предложено добавить файлы только что созданного модуля в систему контроля версий.

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

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

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

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

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

Настройки запуска функции «Создать базовый профиль».
Рисунок 2. При выполнении данной конфигурации генерируется базовый профиль.

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

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

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

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

Вот шаги по созданию нового базового профиля с использованием шаблона модуля Macrobenchmark и плагина 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 для создания базовых профилей ( libs.plugins.androidx.baselineprofile ). Этот плагин упрощает генерацию базовых профилей и их последующее сопровождение.

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

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

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

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

Мы рекомендуем создавать базовый профиль, используя шаблон модуля «Базовый профиль» Android Studio (предпочтительно) или шаблон Macrobenchmark , но вы также можете использовать плагин Gradle для создания базового профиля отдельно. Подробнее о плагине 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 baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                uiAutomator { startApp(PACKAGE_NAME) }
            }
        )
    }
    
  4. Обновите файл build.gradle.kts в модуле приложения, например, добавив в :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 .

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

Для проведения сравнительного тестирования базового профиля создайте новую конфигурацию запуска инструментальных тестов Android из действия во боковой панели, которая будет выполнять тесты, определенные в файле StartupBenchmarks.kt . Более подробную информацию о сравнительном тестировании см. в разделах «Создание класса 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

Укажите все необходимые пути выполнения кода.

Для измерения времени запуска приложения используются два ключевых показателя:

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

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

Для отображения состояния полной отрисовки используйте следующие API Compose:

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