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

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

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

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

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

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

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

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

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

  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 .

    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) и копирует его на хост-компьютер. Чтобы применить сгенерированный профиль к вашему коду, выполните следующие действия:

  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.3.1")
    }
    
  4. Создайте рабочую версию своего приложения, пока применяемые правила HRF компилируются в двоичную форму и включаются в APK или AAB. Затем распространите свое приложение как обычно.

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

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

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

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

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