Сравнение показателей Compose и View

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

Размер APK-файла и время сборки

В этом разделе мы рассмотрим, как переход на Compose влияет на размер APK и время сборки, на примере приложения Sunflower.

Размер APK-файла

Добавление библиотек в проект увеличивает размер APK. Ниже приведены результаты для минифицированного APK-файла каждого проекта с включенным сокращением ресурсов и кода, использующего полный режим R8 и измеренного с помощью APK Analyzer.

Только просмотры Смешанные представления и Compose Только Compose
Размер загрузки 2252 КБ 3034 КБ 2966 КБ

При первом добавлении Compose в Sunflower размер APK увеличился с 2252 КБ до 3034 КБ – на 782 КБ. Сгенерированный APK-файл содержал интерфейс, созданный с помощью Views и Compose. Это ожидаемо, поскольку в Sunflower были добавлены дополнительные зависимости.

И наоборот, когда Sunflower было переведено на Compose, размер APK уменьшился с 3034 КБ до 2966 КБ, то есть на 68 КБ. Это уменьшение было связано с удалением неиспользуемых зависимостей View, таких как AppCompat и ConstraintLayout.

Время на сборку

Добавление Compose увеличивает время сборки приложения, поскольку компилятор Compose обрабатывает composable-функции. Следующие результаты были получены с помощью автономного инструмента gradle-profiler, который выполняет сборку несколько раз, чтобы можно было получить среднее время сборки для отладочной сборки Sunflower:

gradle-profiler --benchmark --project-dir . :app:assembleDebug
Только просмотры Смешанные представления и Compose Только Compose
Среднее время сборки 299,47 мс 399,09 мс 342,16 мс

При первом добавлении Compose в Sunflower среднее время сборки увеличилось с 299 до 399 мс – на 100 мс. Это связано с тем, что компилятор Compose выполняет дополнительные задачи по преобразованию кода Compose, определенного в проекте.

И наоборот, среднее время сборки сократилось до 342 мс (на 57 мс), когда переход Sunflower на Compose был завершен. Это сокращение можно объяснить несколькими факторами, которые в совокупности сокращают время сборки, такими как удаление привязки данных, перенос зависимостей, использующих kapt, в KSP, и обновление нескольких зависимостей до их последних версий.

Сводка

Использование Compose увеличит размер APK-файла и время сборки приложения из-за процесса компиляции кода Compose. Однако эти компромиссы необходимо сопоставить с преимуществами Compose, особенно в отношении повышения производительности разработчиков при внедрении Compose. Например, команда Google Play обнаружила, что для создания интерфейса требуется гораздо меньше кода (иногда на 50 %), что повышает производительность и удобство поддержки кода.

Больше примеров использования вы найдете в статье Adopt Compose for Teams (Внедрение Compose для Teams).

Производительность во время выполнения

В этом разделе рассматриваются темы, связанные с производительностью во время выполнения в Jetpack Compose, чтобы помочь понять, как Jetpack Compose сравнивается с производительностью системы View и как ее можно измерить.

Умные рекомпозиции

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

Профили Baseline

Базовые профили – отличный способ ускорить распространенные пути пользователей. Если в приложении есть базовый профиль, скорость выполнения кода может увеличиться примерно на 30 % с первого запуска, поскольку для включенных путей выполнения не требуется интерпретация и JIT-компиляция.

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

Сравнение с системой View

Jetpack Compose имеет множество улучшений по сравнению с системой View. Эти улучшения описаны в разделах ниже.

Все расширяет View

Каждый элемент View, который отображается на экране, например TextView, Button или ImageView, требует выделения памяти, явного отслеживания состояния и различных обратных вызовов для поддержки всех вариантов использования. Кроме того, владелец пользовательского View должен реализовать явную логику, чтобы предотвратить перерисовку, когда в этом нет необходимости, например при повторяющейся обработке данных.

Jetpack Compose решает эту проблему несколькими способами. В Compose нет явных обновляемых объектов для рисования представлений. Элементы пользовательского интерфейса – это простые composable-функции, информация о которых записывается в композицию в воспроизводимом виде. Это позволяет ограничить явное отслеживание состояния, выделение памяти и обратные вызовы только теми composable-функциями, которым требуются эти функции, вместо того чтобы требовать их для всех расширений данного типа View.

Кроме того, Compose поддерживает умную рекомпозицию, которая позволяет повторно использовать ранее отрисованный результат, если изменения не требуются.

Несколько проходов макета

Традиционные ViewGroups имеют большую выразительность в своих API-интерфейсах измерения и макета, что делает их склонными к множественным проходам макета. Если это происходит в определенных вложенных точках иерархии View, объем работы может увеличиться в геометрической прогрессии.

Jetpack Compose обеспечивает однопроходную компоновку для всех компонуемых макетов через контракт API. Это позволяет Compose эффективно обрабатывать глубокие деревья UI. Если требуется несколько измерений, в Compose есть внутренние измерения.

Посмотреть производительность запуска

При первом показе макета система View должна распаковать его XML-код. Jetpack Compose позволяет избежать этих затрат, поскольку макеты пишутся на Kotlin и компилируются вместе с остальным кодом приложения.

Тестирование Compose

В Jetpack Compose есть заметные различия между производительностью приложения в режимах debug и release. Чтобы получить репрезентативные данные о времени, при профилировании приложения всегда используйте сборку release, а не debug.

Чтобы проверить производительность кода Jetpack Compose, используйте библиотеку Jetpack Macrobenchmark. Чтобы узнать, как использовать его с Jetpack Compose, ознакомьтесь с проектом MacrobenchmarkSample.

Команда Jetpack Compose также использует Macrobenchmark для отслеживания регрессий и проверки производительности по сравнению с представлениями в разных выпусках. Подробные результаты тестирования запуска и прокрутки в Compose и Views на примере приложения Pokedex с открытым исходным кодом можно найти в этом документе.

Установка профиля Compose

Поскольку Jetpack Compose – это несвязанная библиотека, она не использует Zygote, который предварительно загружает классы UI Toolkit и графические объекты системы View. Jetpack Compose использует установку профиля для конечных сборок. Установщики профилей позволяют приложениям указывать критически важный код, который будет компилироваться заранее (AOT) во время установки. В Compose есть правила установки профилей, которые сокращают время запуска и количество задержек в приложениях Compose.