Успокойтесь, и мы поможем вам разобраться в тонкостях исполнительского искусства.
Добро пожаловать на третий день Недели повышения производительности. Сегодня мы продолжаем делиться подробностями и рекомендациями по важным аспектам производительности приложений. Мы рассмотрим оптимизацию на основе профилей пользователей, улучшения производительности Jetpack Compose и особенности работы в фоновом режиме. Давайте начнём.
Оптимизация на основе профиля
Базовые профили и профили запуска являются основополагающими для повышения производительности запуска и работы Android-приложения. Они входят в группу оптимизаций производительности, называемых оптимизацией на основе профилей.
При упаковке приложения d8 dexer берет классы и методы и заполняет файлы classes.dex вашего приложения. Когда пользователь открывает приложение, эти файлы dex загружаются один за другим, пока приложение не сможет запуститься. Предоставив профиль запуска, вы сообщаете d8, какие классы и методы следует упаковать в первые файлы classes.dex . Такая структура позволяет приложению загружать меньше файлов, что, в свою очередь, повышает скорость запуска.
Профили базовой конфигурации эффективно переносят этапы компиляции «на лету» (JIT) с пользовательских устройств на машины разработчиков. Сгенерированный код, скомпилированный «заранее» (AOT), доказал свою эффективность в сокращении времени запуска и решении проблем с рендерингом.
Профили Trello и базовые профили
Мы спросили инженеров, работающих над приложением Trello, как базовые профили повлияли на производительность их приложения. После применения базовых профилей к основному пользовательскому интерфейсу Trello отметило значительное сокращение времени запуска приложения на 25%.

Благодаря использованию базовых профилей, Trello удалось сократить время запуска своего приложения на 25%.
Базовые профили в Meta
Кроме того, инженеры компании Meta недавно опубликовали статью о том, как они ускоряют работу своих Android-приложений с помощью базовых профилей .

В приложениях Meta команды отметили улучшение различных важных показателей до 40 % после применения базовых профилей.
Подобные технические улучшения помогают повысить удовлетворенность пользователей и успех бизнеса. Обсуждение этой информации с владельцами продукта, техническими директорами и лицами, принимающими решения, также может способствовать ускорению работы вашего приложения.
Начните работу с базовыми профилями.
Для создания базового или стартового профиля необходимо написать макротест , который проверяет работоспособность приложения. В ходе тестирования собираются данные профиля, которые будут использоваться при компиляции приложения. Тесты пишутся с использованием нового API UiAutomator , о котором мы поговорим завтра.
Создать подобный бенчмарк довольно просто, и полный пример можно посмотреть на GitHub .
@Test fun profileGenerator() { rule.collect( packageName = TARGET_PACKAGE, maxIterations = 15, stableIterations = 3, includeInStartupProfile = true ) { uiAutomator { startApp(TARGET_PACKAGE) } } }
Соображения
Начните с написания базового профиля и профиля запуска для макробенчмарк-тестов, описывающих наиболее часто используемый пользователями путь. Это означает основную точку входа пользователей в приложение, которая обычно находится после авторизации . Затем продолжайте писать больше тестовых случаев, чтобы получить более полную картину только для базовых профилей. Вам не нужно охватывать все с помощью базового профиля. Придерживайтесь наиболее часто используемых путей и измеряйте производительность в реальных условиях. Подробнее об этом в завтрашней публикации.
Начните работу с оптимизацией на основе профиля.
Чтобы узнать, как работают базовые профили, посмотрите это видео с саммита разработчиков Android:
А еще посмотрите эпизод Android Build Time, посвященный оптимизации на основе профилирования, для более подробного ознакомления:
У нас также имеется обширная информация о базовых профилях и профилях стартапов, с которой можно ознакомиться подробнее.
Улучшения производительности Jetpack Compose
Вклад команды разработчиков в повышение производительности пользовательского интерфейса Android оправдал себя. Начиная с версии 1.9 Jetpack Compose, рывки при прокрутке снизились до 0,2 % во внутреннем тесте производительности при длительной прокрутке.

Эти улучшения стали возможны благодаря ряду функций, включенных в последние версии.
Настраиваемое окно кэша
По умолчанию, в режиме отложенной компоновки (lazy layouts) элемент компонуется заранее только в направлении прокрутки, и после того, как элемент исчезает с экрана, он удаляется. Теперь вы можете настроить количество сохраняемых элементов, используя часть размера области просмотра или dp. Это помогает вашему приложению выполнять больше работы на начальном этапе, а после включения возможности приостановки компоновки между кадрами — более эффективно использовать доступное время.
Чтобы начать использовать настраиваемые окна кэширования, создайте экземпляр LazyLayoutCacheWindow и передайте его в ваш ленивый список или ленивую сетку. Измерьте производительность вашего приложения, используя разные размеры окна кэширования, например, 50% от области просмотра. Оптимальное значение будет зависеть от структуры вашего контента и размера элементов.
val dpCacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)
val state = rememberLazyListState(cacheWindow = dpCacheWindow)
LazyColumn(state = state) {
// column contents
}Пауза в композиции
Эта функция позволяет приостанавливать создание композиций и распределять работу над ними на несколько кадров. API-интерфейсы были добавлены в версии 1.9, и теперь они используются по умолчанию в версии 1.10 в режиме отложенной предварительной загрузки макета. Наибольшую пользу вы получите при работе со сложными элементами, требующими длительного времени для создания композиции.

Дополнительные оптимизации производительности Compose
В версиях 1.9 и 1.10 Compose команда также внесла ряд оптимизаций, которые менее очевидны.
Были улучшены несколько API, использующих сопрограммы. Например, при использовании Draggable и Clickable разработчики должны заметить более быстрое время отклика и улучшенное количество выделяемых памяти.
Оптимизация отслеживания прямоугольников компоновки улучшила производительность модификаторов, таких как onVisibilityChanged() и onLayoutRectChanged() . Это ускоряет этап компоновки, даже если эти API явно не используются.
Ещё одним способом повышения производительности является использование кэшированных значений при отслеживании позиций с помощью onPlaced() .
Предварительная загрузка текста на заднем плане
Начиная с версии 1.9, Compose добавляет возможность предварительной загрузки текста в фоновом потоке. Это позволяет предварительно прогревать кэш для ускорения компоновки текста и имеет важное значение для производительности рендеринга приложения. Во время компоновки текст должен передаваться в фреймворк Android, где заполняется кэш слов. По умолчанию это выполняется в потоке пользовательского интерфейса. Перенос предварительной загрузки и заполнение кэша слов в фоновый поток может ускорить компоновку, особенно для длинных текстов. Для предварительной загрузки в фоновом потоке можно передать пользовательский исполнитель любому компоненту, использующему BasicText , передав LocalBackgroundTextMeasurementExecutor компоненту CompositionLocalProvider следующим образом.
val defaultTextMeasurementExecutor = Executors.newSingleThreadExecutor()
CompositionLocalProvider(
LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor
) {
BasicText("Some text that should be measured on a background thread!")
}В зависимости от текста, это может повысить производительность отрисовки текста. Чтобы убедиться в улучшении производительности отрисовки вашего приложения, проведите сравнительный анализ и сравните результаты.
При оценке результатов работы учитываются следующие факторы, влияющие на эффективность выполнения работы.
Фоновая работа — важная составляющая многих приложений. Для выполнения таких задач вы можете использовать такие библиотеки, как WorkManager или JobScheduler:
- Периодическая загрузка аналитических событий.
- Синхронизация данных между серверной частью и базой данных.
- Обработка медиафайлов (например, изменение размера или сжатие изображений).
Ключевой проблемой при выполнении этих задач является баланс между производительностью и энергоэффективностью. WorkManager позволяет достичь этого баланса. Он разработан для обеспечения энергоэффективности и позволяет откладывать выполнение задач на оптимальное время, зависящее от ряда факторов, включая заданные вами ограничения или ограничения, накладываемые системой.
Однако WorkManager — это не универсальное решение. В Android также есть ряд оптимизированных для повышения производительности API, разработанных специально с учетом определенных распространенных сценариев использования (Core User Journeys, CUJ).
Список некоторых из них, включая обновление виджета и получение данных о местоположении в фоновом режиме, можно найти на целевой странице «Фоновые операции» .
Инструменты локальной отладки для фоновой работы: типичные сценарии
Для отладки фоновых процессов и понимания причин задержки или сбоя задачи необходимо иметь представление о том, как система планирует ваши задачи.
Чтобы помочь в этом, WorkManager предлагает несколько связанных инструментов для локальной отладки и оптимизации производительности (некоторые из них работают и для JobScheduler!). Вот несколько распространенных сценариев, с которыми вы можете столкнуться при использовании WorkManager, и объяснение инструментов, которые можно использовать для их отладки.
Отладка причин, по которым запланированные задачи не выполняются.
Задержка выполнения запланированных задач или их полная невыполнение могут быть вызваны рядом факторов, включая несоблюдение заданных ограничений или наличие ограничений , установленных системой .
Первым шагом в выяснении причин, по которым запланированная работа не выполняется, является подтверждение успешного планирования работы . После подтверждения статуса планирования необходимо определить, существуют ли какие-либо невыполненные ограничения или предварительные условия, препятствующие выполнению работы.
Для отладки подобной ситуации существует несколько инструментов.
Инспектор фоновых задач
Инспектор фоновых задач — это мощный инструмент, интегрированный непосредственно в Android Studio. Он обеспечивает визуальное представление всех задач WorkManager и связанных с ними состояний (Выполняется, Поставлен в очередь, Сбой, Успех).
Чтобы отладить причину, по которой запланированные задачи не выполняются с помощью инспектора фоновых задач, обратитесь к перечисленным статусам задач. Статус «В очереди» означает, что ваша задача была запланирована, но все еще ожидает выполнения.
Преимущества: Помимо удобного просмотра всех задач, этот инструмент особенно полезен при работе с цепочками задач. Инспектор фоновых задач предлагает графическое представление, позволяющее визуализировать, повлиял ли сбой предыдущей задачи на выполнение следующей.

Список задач в окне инспектора фоновых задач

Графическое представление инспектора фоновых задач
adb shell dumpsys jobscheduler
Эта команда возвращает список всех активных заданий JobScheduler (включая рабочие процессы WorkManager) вместе с указанными ограничениями и ограничениями, заданными системой. Она также возвращает историю заданий.
Используйте это, если хотите просмотреть запланированные задачи и связанные с ними ограничения другим способом. Для версий WorkManager, предшествующих WorkManager 2.10.0, adb shell dumpsys jobscheduler вернет список рабочих процессов с этим именем:
[package name]/androidx.work.impl.background.systemjob.SystemJobService
Если в вашем приложении несколько обработчиков событий, обновление до WorkManager 2.10.0 позволит вам видеть имена обработчиков и легко различать их:
#WorkerName#@[package name]/androidx.work.impl.background.systemjob.SystemJobService
Преимущества: Эта команда полезна для понимания наличия каких-либо системных ограничений, которые невозможно определить с помощью инспектора фоновых задач. Например, она вернет резервный сегмент вашего приложения , который может влиять на временной интервал, в течение которого завершается запланированная работа.
Включить отладочное логирование
Вы можете включить пользовательское логирование , чтобы просматривать подробные журналы WorkManager, к которым будет прикреплено WM— .
Преимущества: Это позволяет отслеживать планирование работ, выполнение ограничений и события жизненного цикла, а также просматривать эти журналы в процессе разработки приложения.
WorkInfo.StopReason
Если вы заметили непредсказуемую производительность конкретного воркера, вы можете программно узнать причину остановки воркера при предыдущей попытке запуска с помощью WorkInfo.getStopReason .
Рекомендуется настроить приложение на отслеживание WorkInfo с помощью getWorkInfoByIdFlow, чтобы определить, не влияют ли на вашу работу фоновые ограничения, сбои, частые таймауты или даже остановка работы пользователем.
Преимущества: Вы можете использовать WorkInfo.StopReason для сбора полевых данных о производительности ваших сотрудников.
Отладка проблемы с высокой длительностью блокировки пробуждения, вызванной WorkManager, которая была выявлена системой Android Vitals.
В Android Vitals есть метрика чрезмерного количества частичных блокировок пробуждения, которая указывает на блокировки пробуждения, способствующие разряду батареи. Возможно, вас удивит, что WorkManager получает блокировки пробуждения для выполнения задач , и если количество блокировок пробуждения превышает пороговое значение, установленное Google Play, это может повлиять на видимость вашего приложения. Как можно отладить причину такого большого количества блокировок пробуждения, связанных с вашей работой? Вы можете использовать следующие инструменты.
Панель мониторинга жизненно важных показателей Android
Сначала убедитесь на панели мониторинга Android Vitals "Чрезмерная блокировка пробуждения" , что длительная блокировка пробуждения вызвана WorkManager, а не будильником или другой блокировкой пробуждения. Вы можете использовать документацию " Идентификация блокировок пробуждения, созданных другими API" , чтобы понять, какие блокировки пробуждения удерживаются из-за WorkManager.
Перфетто
Perfetto — это инструмент для анализа системных трассировок. При использовании его для отладки WorkManager вы можете просмотреть раздел «Состояние устройства», чтобы узнать, когда началась ваша работа, как долго она выполнялась и как она влияет на энергопотребление.
В разделе «Состояние устройства: Задания» можно увидеть все запущенные рабочие процессы и связанные с ними блокировки пробуждения.

Раздел Device State в Perfetto, отображающий выполнение процессов CleanupWorker и BlurWorker.
Ресурсы
Для получения обзора доступных методов отладки в других сценариях, с которыми вы можете столкнуться, обратитесь к странице «Отладка WorkManager» .
Чтобы на практике опробовать некоторые из этих методов и узнать больше об отладке WorkManager, ознакомьтесь с практической работой по расширенному WorkManager и тестированию .
Следующие шаги
Сегодня мы вышли за рамки простого сокращения кода и рассмотрели, как среда выполнения Android и Jetpack Compose фактически отображают ваше приложение. Будь то предварительная компиляция критически важных участков кода с помощью базовых профилей или сглаживание состояний прокрутки с помощью новых функций Compose 1.9 и 1.10, эти инструменты ориентированы на удобство использования вашего приложения. И мы подробно углубились в лучшие практики отладки фоновой работы.
Спросите Android
В пятницу мы проведём прямую трансляцию вопросов и ответов по теме производительности. Задавайте свои вопросы прямо сейчас, используя хэштег #AskAndroid, и получите ответы от экспертов.
Задача
В понедельник мы предложили вам включить R8. Сегодня же мы просим вас создать один базовый профиль для вашего приложения.
В Android Studio Otter мастер модуля «Генератор базового профиля» делает этот процесс проще, чем когда-либо. Выберите наиболее важный для пользователя сценарий — даже если это просто запуск приложения и вход в систему — и сгенерируйте профиль.
Получив его, запустите Macrobenchmark, чтобы сравнить CompilationMode.None и CompilationMode.Partial .
Делитесь результатами улучшения времени запуска вашего проекта в социальных сетях, используя хэштег #optimizationEnabled .
Смотрите завтра!
Вы уменьшили размер своего приложения с помощью R8 и оптимизировали время выполнения с помощью оптимизации на основе профилирования. Но как доказать эти достижения заинтересованным сторонам? И как выявлять регрессии до того, как они попадут в продакшн?
Присоединяйтесь к нам завтра на 4-й день: Руководство по выравниванию производительности , где мы подробно расскажем, как измерять ваш успех, начиная от полевых данных в Play Vitals и заканчивая подробным локальным отслеживанием с помощью Perfetto.
Продолжить чтение

Инструкции
При разработке новых функций производительность приложения часто отходит на второй план. Однако, хотя разработчики не всегда задумываются об этом, пользователи могут точно увидеть, в каких областях производительность вашего приложения отстает.
Ben Weiss • 3 мин чтения

Инструкции
Понимая, что чрезмерный расход заряда батареи является одной из главных проблем для пользователей Android, Google предпринимает значительные шаги, чтобы помочь разработчикам создавать более энергоэффективные приложения.
Alice Yuan • 8 мин чтения

Инструкции
Мы хотели предоставить вам примеры функций, использующих искусственный интеллект, как на устройствах, так и в облаке, и вдохновить вас на создание восхитительных впечатлений для ваших пользователей.
Thomas Ezan , Ivy Knight • 2 мин чтения
Будьте в курсе событий
Получайте еженедельно самые свежие новости о разработке Android прямо на свою электронную почту.







