Успокойтесь, и мы поможем вам разобраться в тонкостях исполнительского искусства.
Добро пожаловать на третий день Недели повышения производительности. Сегодня мы продолжаем делиться подробностями и рекомендациями по важным аспектам производительности приложений. Мы рассмотрим оптимизацию на основе профилей пользователей, улучшения производительности 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, и объяснение инструментов, которые можно использовать для их отладки.
Отладка причин, по которым запланированные задачи не выполняются.
Scheduled work being delayed or not executing at all can be due to a number of factors, including specified constraints not being met or constraints having been imposed by the system .
Первым шагом в выяснении причин, по которым запланированная работа не выполняется, является подтверждение успешного планирования работы . После подтверждения статуса планирования необходимо определить, существуют ли какие-либо невыполненные ограничения или предварительные условия, препятствующие выполнению работы.
Для отладки подобной ситуации существует несколько инструментов.
Инспектор фоновых задач
Инспектор фоновых задач — это мощный инструмент, интегрированный непосредственно в 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 мин чтения
ИнструкцииХотя производительность приложений часто ассоциируется с плавным пользовательским интерфейсом и быстрым запуском, память служит негласным фундаментом, на котором строятся эти видимые показатели. Не секрет, что мы наблюдаем сдвиг, при котором объем памяти устройства становится важнее, чем когда-либо.
Alice Yuan , Ajesh Pai , Fung Lam • 10 минут чтения
ИнструкцииСегодня мы рады объявить о появлении новых подтвержденных учетных данных электронной почты, выданных Google, которые разработчики теперь могут получать напрямую через API цифровых учетных данных Credential Manager в Android.
Niharika Arora , Jean-Pierre Pralle • Чтение 3 минуты
Получайте еженедельно самые свежие новости о разработке Android прямо на свою электронную почту.






