eFusion 30 декабря 2020

📱 Jetpack Compose – до и после

В этой статье мы разберемся, как на примере Tivi изменится скорость сборки, размер APK и объем кода после миграции приложения на Jetpack Compose.
📱 Jetpack Compose – до и после

Перевод публикуется с сокращениями, автор оригинальной статьи Chris Banes.

Приложение

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

Tivi сильно модулированный софт. Каждый «экран» UI завернут в собственный модуль Gradle (ui – $NAME). Каждый из этих экранов реализован в виде фрагмента, а затем собран вместе с помощью AndroidX Navigation. Чтобы дать вам представление о его структуре, рассмотрим граф:

📱 Jetpack Compose – до и после

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

Примечание
Модульная структура Tivi совсем неидеальна и приложение не метит на звание лучшего. Присутствует слишком много зависимостей модулей UI (вверху) от базовых модулей (внизу). В идеале каждый слой должен быть отделен.

Прежде чем была начата миграция на Compose, в Tivi использовались все классные UI-штуки, доступные разработчикам Android: Data Binding, Epoxy, Material Design Components, Insetter DBX, MotionLayout и многие другие.

Первый этап

Модульная природа всего приложения означала, что сама миграция может быть выполнена только по частям – по одному фрагменту за раз, что и было сделано в течение 11 месяцев и 46 pull-реквестов.

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

А теперь давайте рассмотрим некоторые показатели.

Метрики

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

  • Pre-Compose. Это коммит, выполненный до первого PR. В нем добавлена поддержка Compose.
  • Mid-transition. В этом коммите, все UI-экраны реализованы в Compose, но AppCompat и MDC все еще местами показываются.
  • Entirely Compose. Данный PR знаменует полное удаление всех следов AppCompat, MDC и т. д.

Размер APK

Показатель, больше всего интересующий пользователей – размер APK.

Результаты приведены для уменьшенного релиза APK (с использованием R8), с применением resource shrinking и измерением с помощью APK Analyzer.

Диаграмма, показывающая размер APK Tivi
Диаграмма, показывающая размер APK Tivi
Диаграмма, показывающая метод подсчета Tivi
Диаграмма, показывающая метод подсчета Tivi

Немного о цифрах

  • На графике изображен размер APK-файла из APK Analyzer, а не размер после загрузки.
  • Как для Mid-transition, так и Entirely Compose (отмечены *) общий размер APK равен 560 КБ из-за дополнительных файлов TTF, которых не было в Pre-Compose APK. Это связано с тем, что Compose не поддерживает загружаемые шрифты (проблема отслеживания), поэтому необходимо включить их в пакет. Столбец «adjusted» показывает более правильное сравнение, исключая файлы шрифтов.
  • Mid-transition имеет увеличенный размер, потому что он включает в себя как Jetpack Compose, так и AppCompat, MDC и т. д.
  • В течение всего процесса миграции было много обновлений зависимостей, в основном библиотеки рантайма – скорее всего это повлияло на метрики размера APK.
  • Также был обновлен Gradle (с 6.0.1 до 6.7.0), плагин Android Gradle (с 3.6.0 до 4.2.0) и Kotlin (с 1.3.61 до 1.4.20) – они могут оказать влияние на скорость билда.

При сравнении «adjusted» значений с «Pre-Compose» мы наблюдаем уменьшение размера APK на 41% и сокращение размера методов на 17% при использовании Compose.

Эти числа показывают, сколько места занимают AppCompat, MDC и т. д. в приложении, но также и то, как малоэффективны инструменты минификации, когда вам нужно сохранить все View-классы, если они используются из файлов макета.

Количество кода

📱 Jetpack Compose – до и после

Да, подсчет исходных строк кода не является особенно полезной статистикой при сравнении программных проектов, но он дает представление о том, как все меняется.

Для этого теста применялся инструмент cloc. Используем следующую команду, чтобы исключить из билда, любые сгенерированные и конфигурационные файлы:

        cloc . --exclude-dir=build,.idea,schemas
    
📱 Jetpack Compose – до и после

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

Интересно также, что общее количество кода в Kotlin тоже снизилось. Теперь в проекте меньше шаблонного кода, и автор смог удалить много кода view helper & utility.

Скорость сборки

Скорость сборки – это показатель, о котором разработчики очень переживают и пытаются его улучшить. Удаление большого количества процессоров аннотаций заметно сказалось на скорости билда, что будет видно дальше.

Тестовая установка

Измерения, приведенные ниже, были произведены на разных процессорах.

Тестовая машина – это Lenovo P920 с 192GB ОЗУ и производительным процессором Xeon Gold 6154. Ясное дело, что такая конфигурация не является типичной для разработчика, поэтому чтобы сделать тест более реалистичным, производительность процессора была урезана до минимальной тактовой частоты:

        # Use performance governor to allow tweaking of max freq
sudo cpupower frequency-set -g performance
# Set max frequency to CPU minimum: 1.2GHz
sudo cpupower frequency-set -u 1.2GHz
    

Для подготовки удаленного кеша использовали команду:

        ./gradlew assembleDebug
    

Чтобы запустить тесты, следующая команда была выполнена в цикле 5 раз:

        ./gradlew --profile \
           --offline \
           --rerun-tasks \
           --max-workers=4 \
           assembleDebug
    

Параметр --max-workers не является строго необходимым, но Gradle будет использовать все 64 ядра, доступные на этом процессоре по умолчанию. Ограничение до 4 более сопоставимо с типичными процессорами ноутбуков.

Результаты

Вы можете увидеть результаты тестирования ниже, используя значение «Total Build Time» из каждого отчета.

📱 Jetpack Compose – до и после

Результат показал удивительные значения, потому как цифры очень близки. Ожидалось, что «Entirely Compose» будет быстрее, из-за удаления процессоров аннотаций.

Детализация результатов показывает, что время выполнения kapt остается одинаковым во всех прогонах, вероятно, потому что в проекте все еще используется Dagger/Hilt и Room.

Заключение

Можно сделать следующий вывод: Compose оказывает положительное (или нейтральное) влияние на большинство метрик программиста. Имея это в виду, наряду со значительно возросшей производительностью труда использующих Compose разработчиков – это будущее создания пользовательского интерфейса на Android.

Дополнительные материалы:

Источники

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ