Отключаем Jetifier и ускоряем сборку: опыт Тинькофф.Бизнес

f685ca5d48af6f852d7a02b2854b4e59.png

Привет, Хабр!

Уже пять лет наша команда разрабатывает Тинькофф.Бизнес — мобильный банк для юридических лиц и ИП. За это время наше android-приложение успело набрать целых 200 модулей и 400 тысяч строк компилируемого кода.

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

В этой статье я расскажу и покажу, как мы ускорили билд, отключив Jetifier.

Преамбула

Jetifier был представлен еще в далеком 2018 году вместе с AndroidX — классной заменой support библиотекам, компоненты которой могут поддерживаться и обновляться независимо друг от друга.

Сам по себе Jetifier довольно сложен, но принцип его работы прост как три копейки: он проходится по всем библиотекам, которые есть у вас в проекте и заменяет в них android.support зависимости на их androidx аналог.

В результате мы получаем еще один шаг сборки, который может занять довольно много времени, а до появления AGP 4.1.0 еще и никак не кэшировал результат своего выполнения и замедлял даже инкрементальный билд.

Конечно же нам хотелось бы избавиться от него. Как?

Отключаем Jetifier

На самом деле все может быть довольно просто. Попробуйте зайти в gradle.properties

и проставить там заветный android.enableJetifier=false, а затем выполнить Gradle sync и build. Получилось? Если нет — вы увидите примерно следующую ошибку:

Это связано с тем, что в classpath есть легаси android.support зависимость, и она конфликтует с ее androidx-аналогом. Для отключения Jetifier’а нужно сделать так, чтобы в графе зависимостей не было ни одной саппорт-библиотеки. Давайте посмотрим на полный список зависимостей в нашем проекте. Открываем терминал и запускаем следующую команду:

./gradlew :app:dependencies --configuration=releaseRuntimeClasspath

c3eaff287986aff09ce7056b2a2778d5.png

Здесь можно видеть, что модуль app использует mosby-mvp, который тянет за собой support-библиотеки.

В случае, если ваш проект довольно большой и имеет много зависимостей, :app:dependencies может быть не совсем удобным способом отлавливать легаси-зависимости, на этот случай можно использовать плагин Can I Drop Jetifier: он анализирует граф зависимостей проекта и смотрит, есть ли среди них те, что ссылаются на android.support библиотеки, агрегируя их в один список.

Давайте применим плагин и вызовем ./gradlew -Pandroid.enableJetifier=false canIDropJetifier

1fd13529515a9f67ad1d6dd66b4d2aa3.png

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

Отлично! Давайте теперь на примере mosby.mvp рассмотрим способ миграции библиотеки на androidx.

Для этого нам нужно выполнить несколько шагов:

  1. Проверить версию библиотеки — если есть более новая, в которой нет support зависимостей — обновляемся. Если нет — переходим на следующий шаг.

  2. Найти библиотеку в репозиториях. Например, mosby.mvp лежит на maven

  3. Скачиваем .pom и .aar файлы.

  4. Открываем .pom файл и меняем  — добавляем в него префикс jetified., чтобы ничего не перепутать

  5. Вручную заменяем все android.support зависимости на их androidx аналог, воспользовавшись этими маппингами.

  6. Если зависимости содержат другие артефакты из этой группы, использующие android.support — с ними придется провести такую же процедуру.

  7. Скачиваем jetifier-standalone и прогоняем через него скачанный .aar файл с зависимостью.

    ./jetifier-standalone -i -o

  8. Загружаем .pom и .aar файлы в любой доступный вам менеджер репозиториев. У нас это Nexus, если же у вас его нет — можете просто положить .aar к себе в проект.

Готово! Выполнив эти шаги, мы получаем jetified-артефакт, который можем использовать у себя в проекте.

Давайте посмотрим, какой выигрыш мы от этого получили.

Метрики

Для сбора метрик отлично подойдет Gradle Profiler. Для его запуска мы написали простой .sh скрипт и положили его в корневую папку проекта.

#!/bin/bash
echo "Cloning gradle-profiler repository..."

git clone https://github.com/gradle/gradle-profiler.git
cd gradle-profiler
./gradlew installDist
cd ..
./gradle-profiler/build/install/gradle-profiler/bin/gradle-profiler --benchmark --iterations 4 --warmups 3 --project-dir ./ :rko:assembleDebug

echo "searching for statistics..."

medians=$(grep "median" profile-out/benchmark.csv)
IFS=', ' read -r -a array <<< "$medians"

echo "configurationTime = ${array[1]}"
echo "syncTime = ${array[2]}"
 ...

Далее после прогона мы получили следующие метрики:

Метрика

Jetified

Non-Jetified

Mean

23,5 sec

28,5 sec

Min

22 sec

26 sec

Max

25 sec

31 sec

У нас было не так много легаси-зависимостей, которые пришлось перевести на androidx руками, но тем не менее, прогнав на них Jetifier, нам удалось отнять целых 5 секунд из среднего времени сборки. При большом количестве зависимостей эта цифра будет только расти.

Еще больше метрик и самых разных новостей о Тинькофф.Бизнес можно увидеть у нас в Телеграм-канале Tinkoffhere!

© Habrahabr.ru