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
Размер установочного файла с течением времени для приложений 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
Рентгеновский снимок Emerge Size Analysis

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

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

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

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

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

Размер двоичного символа в v22.35.0 (до Xcode 14)
Размер двоичного символа в v22.35.0 (до Xcode 14)
Размер двоичного символа в v22.36.1 (после 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 — TurboTaxMint и Quickbooks — имеют общий установочный размер 1,37 ГБ. Они могли бы сэкономить 578 МБ (42% размера), просто удалив двоичные символы.

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

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

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

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

  • "Deployment Postprocessing" = "Yes"

  • "Strip Linked Product" to "Yes"

  • "Additional Strip Flags" to -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
Обзор приложения American Airlines для iOS в App Store

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

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

- Документация Play Console

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

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

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

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

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

Авторы статьи: Макс Топольски и Джош Коэнзаде.
Перевод и адаптация: SwiftBook.

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

Подписывайся на наши соцсети: Telegram / VKontakte
Вступай в открытый чат для iOS-разработчиков: t.me/swiftbook_chat
Смотри бесплатные уроки по iOS-разработке с нуля

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


  1. Krypt
    05.12.2022 17:35
    +11

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

    > которые окончательно не связаны с Xcode 14.
    > that aren't definitively attributable to Xcode 14.
    "которые не могут быть однозначно связанны с Xcode 14."


    1. SwiftBook Автор
      05.12.2022 22:15

      спасибо


  1. Vasily_Pechersky
    05.12.2022 17:56

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


    1. Holix
      05.12.2022 18:16
      +2

      Потому что современное ПО -- поделки. Важно побыстрее, с меньшими усилиями и минимальным порогом вхождения для программистов.
      А когда профессиональный программист пишет взрослый код они плачут с фразами: "Сложна! Почему так сложна!?". И всё ради снижения порога вхождения в профессию. Думать о размере кода и памяти? -- Слишком сложно! Даёшь автоматическую кучу! Давайте ещё больше кода для упрощения работы с памятью и "рисования" кода! Вот -- доупрощались. Зато программу может сляпать любой ребенок!
      P.S. Извините, наболело..


      1. aamonster
        05.12.2022 22:27
        +3

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


    1. Krypt
      05.12.2022 18:21
      +5

      Касательно конкретно iOS, как правило принцип "всё своё ношу с собой". На iOS, Swift runtime до определённого момента даже не был частью системы, например. Каждое приложение включало себя рантайм. Так же "fat binaries", которые включают себя код для нескольких архитектур сразу.

      На данный момент Apple перепаковывает приложение на своей стороне и отдаёт только нужные бинарники, но в свете этой статьи не факт, что он будет делать это дальше.


      1. aamonster
        05.12.2022 22:30

        Вот да, я тоже было задался вопросом – вырос размер заливаемого в app store бинарника или отдаваемого юзеру... Но прочитал дальше: судя по "жалобам клиентов" – второе :-(. Это весьма неприятно и непонятно, должны же отрезать неподходящие архитектуры.


        1. daniilpashin
          06.12.2022 10:56
          +2

          Сейчас архитектура вообще только одна - arm64. Если конечно вы не таргетируетесь на поддержку 9 iOS и 5 айфона, что в принципе сейчас невозможно. А arm64e пока находится в бета-тесте и возможно в магазине никогда и не будет. Так что ждем какую-нибудь arm128 тогда уж.


    1. grishkaa
      06.12.2022 01:38
      +3

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

      Приложение для андроида, которым я сейчас занимаюсь, в релизной сборке весит 3 (три) мегабайта. Гугл плей ещё дополнительно скукоживает, убирая ресурсы вроде ненужных этому конкретному пользователю локализаций. Люди удивляются, по большей части в хорошем смысле.

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


    1. mSnus
      06.12.2022 14:20

      Потому что используют готовые пакеты в огромном количестве, зато софт можно выпускать очень быстро


  1. Yak52
    05.12.2022 19:34
    +7

    • «Удалить связанный продукт» на «Да»

    • «Дополнительные флаги полосы» на -rSTx

    • Все остальные настройки зачистки на значения по умолчанию

    А это не вы случайно подрабатываете русским переводом у китайцев для Алиэкспресса?


    1. SwiftBook Автор
      05.12.2022 22:22
      -2

      Переводчик перестарался, исправили. Спасибо


  1. Solovej
    05.12.2022 20:12
    +2

    Я так понял статья Copy-Past из переводчика в Safari.

    Василий, было бы хорошо делать вычитку статьи перед публикацией.

    А что настройки Xcode - русифицировали???

    • "Deployment Postprocessing" = "Yes"

    • "Strip Linked Product" to "Yes"

    • "Additional Strip Flags" to -rSTx

    • All other stripping settings to their defaults


  1. kovserg
    05.12.2022 22:33
    +2

    Ужос какой. Из всех этих букв стало понятно только то что
    1. XCode14 теперь не удаляет отладочную информацию из release (которой раньше там и не было).
    2. Увеличение приложений за счет мусора, вызывают только положительные эмоции. По крайней мере это называют: улучшением. Но тут же зачем-то пристраивают костыли.