Pull to refresh

Размер имеет значение! Часть 1

Reading time4 min
Views5K

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

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

Когда речь идет о большой команде, очень тяжело проконтролировать изменения происходящие в проекте, так как много feature команд, которые добавляет крутые фичи, которые в последствии могут повлиять на размер. Поэтому лучше всего этот контроль сделать автоматизированным, и в этом нам поможет наш специальный flow на CI.

Обнаружение регрессии в development

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

Нашей первой идеей было - что если собирать релизный билд на каждый commit(pull request merge) в development и собирать метрики размера. Но сразу поняли что это не лучшее решение для быстрого решения этой задачи, так как в случае, если 2 коммита одновременно запушатся(push) в development, то тяжело будет сравнить эти 2 apk между собой, так как релизный билд занимает приличное время. Поэтому мы и нашли способ по проще.

1. Предположим, мы выберем определенный коммит в определенное время и запустим с него релизный билд, знакомой нами gradle командой:

./gradlew assembleRelease

И в результате, с полученного apk, мы собираем и выгружаем метрики(размер apk, текущий использованный commit, версия приложения, дата и тд например в формате json) в любое вам хранилище(gcloud), главное чтоб можно было туда загружать наши артефакты и загрузить к себе обратно, когда будет нужно. Также загружаем собранный релизный apk, он нам будет нужен в последующей проверке размера приложения. Используем gsutil command line tool:

gsutil cp "$build_size_info.json" "gs://custom_folder/build_size_info.json"
gsutil cp "$current-release.apk" "gs://custom_folder/current-release.apk"

2. Выбираем следующий определенный commit в development, через некоторые время, к примеру, через 3 часа(на свой выбор). Также собираем релизный билд на этом commit, все также загружаете apk, метрики. Но теперь нам нужно загрузить из хранилища предыдущий билд, который мы собирали 3-мя часами ранее, и сравниваем предыдущий и текущий apk. Но просто сравнение размеров apk нам недостаточно, хотелось бы подробное сравнение, в котором мы сможем выяснить, какие файлы были добавлены или удалены. В этом нам поможет diffuse tool by Jake Wharton, который может сравнивать apk, aab, jar, aar файлы и показать детальную информацию сравнения.

java -jar diffuse-binary.jar diff $prev.apk $current.apk > $report.txt
gsutil cp "$report.txt" "gs://custom_folder/report.txt"

Результат сравнения записываем в файл report.txt и загружаем в наше хранилище, чтобы далее можно было по ссылке посмотреть. Если показать содержимое report.txt, то будет выглядеть вот так:

Файл будет также содержать больше деталей про измененные ресурсы(добавленные, удаленные), но нам может быть достаточно и этой информации, чтобы понять что послужило регрессией. Нас интересует столбец diff, который показывает на сколько были изменены файлы внутри apk. В данном случае, мы видим что значительно был изменен файл arsc(resources.arsc), который хранит в себе все компилируемые ресурсы(drawable/.xml, layout/, raw/, values/ etc.). И мы понимаем что кто-то замержил в development Pull request, в котором были добавлены компилируемые ресурсы и мы можем найти этот commit в git историй.

3. Чтоб облегчить задачу поиска коммита, который послужил регрессией, мы можем собрать все вовлеченные коммиты между коммитами когда был проверен размер приложения. Для этого вызываем команду git:

git rev-list --ancestry-path "$prev_commit_hash".."$current_commit_hash"

Итог:

В результате, наш workflow на CI будет выглядеть так:

Схема полного workflow на CI
Схема полного workflow на CI

Чтобы запускать проверку каждые 3ч, вы можете назначить задачу в вашем CI, либо запускать в зависимости от времени(зависит от возможностей вашего CI).

Если обнаружена регрессия размера, можете оповестить команду со ссылкой(report.txt в gcloud) на детальную информацию сравнения, в последствий ответственный разработчик может выявить причину и найти конкретный commit в development, который послужил регрессией и исправить, либо ревертнуть изменения.

Недостатки

1. Позднее обнаружение регрессии - узнаем о регрессии только после того, как изменения уже были влиты в development

2. Требует ручной работы - все таки это не полностью автоматизированный процесс, так как, как только происходит регрессия, разработчику приходится проверять результат сравнения и искать конкретный commit, внутри всех вовлеченных коммитов.

3. Собираем универсальный apk - который содержит ресурсы для всех конфигураций девайсов, что влияет на размер приложения. Эта проблема решается внутри Google Play, куда нам надо загрузить App Bundle, а внутри собирается apk в зависимости от конфигурации конкретного устройства.

Все эти недостатки мы будем решать в следующей части статьи.

Tags:
Hubs:
+5
Comments12

Articles