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

Мы, как разработчики, хотим сделать наше приложение доступным многим пользователям, чтоб они могли скачивать и устанавливать наше приложения без каких-либо проблем. И одна из метрик связанный с этой целью является размер нашего приложения - большой размер приложения может послужить причиной проблем при загрузке и установки на устройствах, с ограниченным размером памяти или медленным интернетом. И чем больше мы уменьшаем размер нашего приложения, тем выше становится конверсия установок, как подробно сказано об этом в отдельной статье. Поэтому нам бы хотелось не только оптимизировать размер, но и иметь мониторинг изменения размера и могли обнаружить увеличение размера до того, как это попало в 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 в зависимости от конфигурации конкретного устройства.

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

Комментарии (7)


  1. Zara6502
    16.09.2022 08:00
    +5

    я правильно вас понял что увеличение размера apk файла на 105 Кб вы воспринимаете как "шеф, всё пропало"? а вы могли бы пойти работать в сбербанк? их приложение пухнет безостановочно, когда доросло до 2,5 Гб и я пожаловался в СБ они просто сказали переустановить приложение ) (да, я знаю что это не apk а кеш программы, но и 2,5Гб данных для работы им не нужно это точно)


    1. akniyetc Автор
      16.09.2022 10:53

      Здесь имеется в виду именно размер загружаемого из google play apk(download size), поэтому 105Кб в течении 3ч. это значимая цифра, так как apk обычно все ресурсы хранит оптимально(помимо не компилируемых ресурсов). Насчет контроля размера кэша приложения, я думаю мало кто об этом заботится, и сомневаюсь о реализуемости, даже если реализуемо, то стоит ли оно того. Зачастую это решается простой очисткой кэша.


      1. Zara6502
        16.09.2022 12:02

        поэтому 105Кб в течении 3ч. это значимая цифра

        что значит "в течение 3ч"?

        Зачастую это решается простой очисткой кэша

        Вы предлагаете пользователю следить за размером кеша и чистить его самостоятельно? А разработчики софта не могут написать одну строчку if(cache.size>1M) cache.flush при старте программы?


        1. mSnus
          16.09.2022 13:29

          Это же паттерн "Барахольщик": - а давай выкинем старье с балкона? - нет, вдруг там что-то ценное или пригодится! И в результате проще устроить капремонт (сбросить весь кэш), чем разбираться, что нужное, а что нет.


        1. akniyetc Автор
          16.09.2022 13:45

          что значит "в течение 3ч"?

          Это примерный промежуток времени(3 часа), для проверки размера, у каждого может быть свое, но суть в том, что для изменении произошедших в течении последних 3 часов - 105Кб это значительное изменение. Значение промежутка времени и значение лимита для размера можете задавать сами. В нашем случае, мы проверяем размер каждые 3 часа, с лимитом 75Кб(для примера).

          Вы предлагаете пользователю следить за размером кеша и чистить его самостоятельно? А разработчики софта не могут написать одну строчку if(cache.size>1M) cache.flush при старте программы?

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


          1. Zara6502
            17.09.2022 03:28

            105Кб это значительное изменение

            почему?

            Думаю это не так просто будет реализовать, так как в кэше могут храниться и важная информация, которую лучше не стоит очищать

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


            1. akniyetc Автор
              17.09.2022 20:20

              почему?

              относительно значительное*
              Например в играх такое значение не существенно.
              если вопрос, почему у нас в приложений это так, то лимит в 75Kb мы определили на начальном этапе. Приложение доставки еды, обычно не требует колоссальных ресурсов, да и нужно постараться превысить лимит за такой короткий срок. Этот лимит не говорит, что "Тревога! Все пропало!", а лишь сигнализирует, что где-то не хватает оптимизаций, и дает знать что и как было изменено.