Как Xcode 14 непреднамеренно увеличивает размер приложения

22 ноября 2022

10.11.22 Макс Топольски и Джош Коэнзаде.                  Follow @jshchnz
Расчетное время чтения: 5-10 минут.                           

 

Переход на Xcode 14

 

Xcode 14 был выпущен 12 сентября со многими новыми функциями и улучшениями. "Первое, что вы заметите", это то, что Xcode быстрее и на 30% меньше.1 Повышенный параллелизм делает создание проектов на 25% быстрее, а длительные тесты до 30% быстрее.

Вскоре после выпуска Xcode 14 в ряде приложений для iOS был замечен значительный прирост в размере. Сначала мы написали в Твиттере о наблюдении большого скачка в приложении Zillow для iOS. Zillow не был отдельным примером.

Между серединой сентября и началом октября:

•    8 октября размер установки приложения Nike для iOS составлял 182,2 МБ. Неделю спустя он был равен 322,1 МБ (+77%)

•    American Airlines выросла с 182,2 МБ до 389,1 МБ,  - Xcode 14 стал причиной увеличения на 76,2 МБ (+113%)

•    Chime увеличен с 162,8 МБ до 212,8 МБ (+31%)

Размер установочного файла с течением времени для приложений Nike, American, Chime и Zillow для iOS


В каждом случае скачок размера связан с тем, что эти приложения впервые выпускаются с Xcode 14. В числе прочих функций, Xcode 14 отключил битовый код по умолчанию.

Xcode больше не создает битовый код по умолчанию... Возможность сборки с помощью битового кода будет удалена в будущем выпуске Xcode. IPA, содержащие битовый код, будут удалены перед отправкой в App Store.
- Примечания к выпуску Xcode 14

Что такое битовый код (биткод)?
Bitcode - это альтернативный способ упаковки приложения, который оставляет часть процесса сборки для Apple после отправки в App Store. Одна из вещей, которую делает Apple, это удаляет двоичные символы.

А удаление двоичных символов?
Удаление двоичных символов - это когда определенные типы метаданных, которые не нужны для запуска приложения в производстве, удаляются из двоичного файла. Это метаданные, которые могут быть полезны до начала производства, например, для создания файлов dSYM, но в производственной сборке только «раздувают» телефон пользователя.

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

Этот блог не о том, является ли устаревший биткод хорошим или плохим, он про выделение менее известного эффекта выпускаемых с помощью Xcode 14 приложений. Ниже мы:

  • Сравним сборки приложения до и после Xcode 14
  • Выясним, какие приложения имели регрессию размера из-за Xcode 14
  • Покажем как любое приложение может удалять бинарный код

 

Сравнение Nike до и после Xcode 14

 

С Xcode 14 любое приложение, которое полагалось на битовый код, больше не обязательно удаляет двоичные символы из своего производственного приложения. Это означает, что приложение может стать намного больше без добавления какой-либо функциональности.

Вот рентгеновский снимок от Emerge Size Analysis для версии 22.35.0 (в соотношении 10/8) приложения Nike для iOS. В этой версии фреймворки составляют 163,7 МБ от размера установки 191,7 МБ. Если вы находитесь у большого экрана, попробуйте взаимодействовать с древовидной картой, чтобы увидеть детализированные разбивки по размерам.

 

Рентгеновский снимок Emerge Size Analysis

В версии 22.36.1 (10/15) фреймворки подскакивают до 293,8 МБ (+127,3 МБ) из общих 322,1 МБ. Обратите внимание на добавление темно-синих “String table", найденных в каждом фреймворке.

Рентгеновский снимок Emerge Size Analysis

Когда мы сравниваем две сборки, мы видим, что практически все увеличение на 130 МБ происходит из-за роста DYLD.String tables. Эти String tables являются ненужными метаданными, которые теперь используются в производстве. 

Сравнение размеров между двумя сборками Nike

Nike вырос с 213,9 КБ двоичных символов (0,11% от общего размера приложения) до 127,5 МБ двоичных символов - почти 40% всего приложения.

Размер двоичного символа в v22.35.0 (до Xcode 14)

Размер двоичного символа в v22.36.1 (после Xcode 14)

В целом, приложение Nike для iOS увеличилось на 130 МБ без каких-либо серьезных изменений.

 

 

Сколько приложений было затронуто

 

Emerge Tools регулярно загружает приложения из App Store для анализа, что позволяет нам обнаружить эти регрессии и присмотреться. Приведенные ниже данные представляют все приложения, где:

  • Есть более 2 МБ двоичных символов
  • Более 5% приложения - это двоичные символы
  • Процент приложения, которое является двоичными символами, вырос по крайней мере на 5% между сборками

Все приложения извлекаются непосредственно из App Store. Предоставленный анализ предназначен только для образовательных целей и не представляет клиентов Emerge Tools.

Каждое из вышеперечисленных приложений, вероятно, регрессировало из-за выпуска с Xcode 14. Тем не менее, есть много других приложений, которые имеют значительную экономию за счет удаления двоичных символов, которые окончательно не связаны с Xcode 14.

Приложение Toyota (v2.0.9), о котором мы твитнули в начале блога, имеет установочный размер 550,2 МБ и может сэкономить 109,8 МБ (20% от общего размера приложения) за счет удаления двоичных символов. Это был первый раз, когда Emerge Tools проанализировало приложение Toyota, и мы не смогли сказать, было ли в нем раздувание двоичных символов в предыдущих сборках.

Есть также такие приложения, как TurboTax, которое мы анализируем еженедельно с апреля 2022 года. TurboTax обеспечивает потенциальную экономию более 100 МБ в каждой сборке, которую мы измерили. Три основных приложения Intuit для iOS — TurboTax, Mint и Quickbooks — имеют общий установочный размер 1,37 ГБ. Они могли бы сэкономить 578 МБ (42% размера), просто удалив двоичные символы.

Ниже приведен список приложений, в которых более 15 МБ двоичных символов, но мы не можем точно сказать, связано ли это с переходом на Xcode 14.

 

Как удалить двоичные символы без битового кода

 

К счастью, удаление двоичных символов из конечного продукта сборки просто. Вот два способа.
Использование настроек сборки Xcode

Вы можете выполнить автоматическую зачистку сборок во время выполнения Архивной сборки, установив:

  • «Постобработка развертывания» = «Да»
  • «Удалить связанный продукт» на «Да»
  • «Дополнительные флаги полосы» на -rSTx
  • Все остальные настройки зачистки на значения по умолчанию

Однако с этим методом вы должны быть осторожны, т.к. настройки одинаковые для всех таргетов. Кроме того, могут быть подводные камни при использовании менеджеров пакетов. Для Cocoapods здесь обсуждается проблема, которая связана с одним возможным решением (убедитесь, что все удаляемые фреймворки являются динамическими, если вы это делаете).


Использование сценария оболочки

 

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

Ниже приведен пример скрипта, который вы можете использовать для удаления двоичных файлов. Огромное спасибо Филипу Бьюзику из Doordash за помощь!

#!/bin/bash
set -e

# if [ "Release" = "${CONFIGURATION}" ]; then # Uncomment and only do this for release builds that you don't need to debug
    
    # Path to the app directory
    APP_DIR_PATH="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}"
    # Strip main binary
    strip -rSTx "${APP_DIR_PATH}/${EXECUTABLE_NAME}"
    # Path to the Frameworks directory
    APP_FRAMEWORKS_DIR="${APP_DIR_PATH}/Frameworks"
    
    # Strip symbols from frameworks, if Frameworks/ exists at all
    # ... as long as the framework is NOT signed by Apple
    if [ -d "$APP_FRAMEWORKS_DIR" ]; then
        find "$APP_FRAMEWORKS_DIR" -type f -perm +111 -maxdepth 2 -mindepth 2 -exec bash -c 'codesign -v -R="anchor apple" "{}" &> /dev/null || (printf "%s\\n" "{}" && strip -rSTx "{}")' \;
    fi
    # Re-sign binaries as necessary
# fi

strip_binary_symbols.sh hosted with ❤ by GitHub

В настройках этапов сборки убедитесь, что флажок «На основе анализа зависимостей» не установлен, чтобы скрипт запускался при каждой сборке. Подробнее об этом методе можно прочитать в нашей документации.

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

 

Почему это имеет значение

 

Как Apple сказала в своем видео про Xcode 14, размер приложения - это первое, что заметит ваш пользователь. И пользователи обращают внимание, как выразился недавний рецензент приложения American Airlines для iOS: 372 мб: приложение слишком большое, постоянно падает


Обзор приложения American Airlines для iOS  в App Store

Документация Play Console от Google имеет аналогичную рекомендацию:

Размер приложения является одним из самых больших факторов, которые могут повлиять на показатели установки и удаления вашего приложения. Важно регулярно отслеживать и понимать, как вы можете уменьшить размеры загрузки и установки вашего приложения.
- Документация Play Console

Хорошо… размер имеет значение… Если предположить, что это правда, как можно было бы избежать этой регрессии?

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

“Привет, ребята из Emerge! Мы только что загрузили нашу первую сборку, сделанную с помощью Xcode 14, и мы видим огромное увеличение в размере, которое в большей степени связано со строковыми таблицами DYLD. Возможно ли, что это артефакт вашего анализа или же это реальное явление? Если да, есть ли у вас какое-либо представление о том, что происходит? Некоторое беглое гугление было не очень полезным.”

Выше приведен Slack от одного из наших клиентов, который спрашивает об увеличении размера своего приложения после перехода на Xcode 14. Они заметили регрессию перед релизом с помощью инструментов непрерывной интеграции Emerge.

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

Оригинал статьи

Содержание