Механизм сборки iOS

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

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

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

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

Замеры времени для приложений

Чтобы включить вывод диагностики MSBuild в Visual Studio для Mac, выполните следующие действия:

  1. Щелкните Visual Studio для Mac > настройки...
  2. В представлении дерева слева выберите "Сборка проектов > "
  3. На панели справа откройте раскрывающийся список детализации журнала и выберите вариант Диагностика: Setting the Log verbosity
  4. Нажмите кнопку ОК.
  5. Перезапустите Visual Studio для Mac.
  6. Выполните очистку и перестройку пакета.
  7. Просмотр диагностических выходных данных на панели ошибок (ошибки просмотра > панелей > ) с помощью кнопки "Вывод сборки"

Замер времени для mtouch

Чтобы отобразить сведения о процессе сборки mtouch, передайте --time --time в качестве аргумента для mtouch на странице Параметры проекта. Результаты будут отображаться в выходных данных сборки, где их можно найти по имени задачи MTouch:

Setup: 36 ms
Resolve References: 982 ms
Extracted native link info: 987 ms
...
Total time: 1554 ms

Подключение из Visual Studio к узлу сборки

Средства Xamarin технически могут выполняться на любом компьютере Mac, где можно запустить OS X 10.10 Yosemite или более поздней версии. Но возможности разработки и времена сборки могут существенно ухудшаться при плохой производительности Mac.

В отключенном режиме Visual Studio на Windows выполняет только этап компиляции C# и не пытается применять компоновку, компиляцию AOT, упаковку приложения в пакет .app или подписывание пакета приложения. (Этап компиляции C# редко является узким местом производительности.) Попытайтесь определить, где в конвейере сборка замедляется путем создания непосредственно на узле сборки Mac в Visual Studio для Mac.

Кроме того, довольно часто причиной задержки может быть сетевое подключение между компьютером Windows и узлом сборки Mac. Это может быть вызвано физической проблемой в сети, скоростью беспроводного соединения или наличием перегруженной машины в цепочке между компьютерами (например, в службе Mac-in-the-cloud).

Советы при работе с эмулятором

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

Симулятор Apple для разработки в iOS отдает приоритет скорости в ущерб совместимости, применяя менее строгую среду для выполнения кода. Такое снижение требований к среде позволяет Xamarin использовать для симулятора компилятор JIT (в отличие от AOT, используемого на устройствах). Это означает, что сборка в машинный код выполняется во время выполнения. Поскольку Mac всегда намного быстрее, чем устройство, это повышает производительность.

Симулятор использует общее средство запуска приложений, позволяя использовать его повторно, тогда как на устройстве его приходится компилировать каждый раз заново.

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

Советы

  • Для сборок:
    • Снимите флажок Оптимизировать изображения PNG в параметрах проекта. Эта оптимизация не нужна для сборок в симуляторе.
    • Для компоновщика выберите вариант Не компоновать. Компоновщик выполняется довольно долго, а значит его отключение ускоряет процесс.
    • Если вы отключите общее средство запуска приложений флажком --nofastsim, сборка симулятора будет работать намного медленнее. Уберите этот флажок, как только в нем отпадет необходимость.
    • Работа с собственными библиотеками проходит медленнее, поскольку в этом случае нельзя применить общее средство запуска в симуляторе. Это означает, что для каждой сборки нужно заново компилировать полный исполняемый файл для конкретного приложения.
  • Для развертывания
    • Всегда оставляйте симулятор работать, если это возможно. На холодный запуск симулятора требуется до 12 секунд.
  • Дополнительные Советы
    • Старайтесь выбирать сборку, а не повторную сборку, поскольку второй вариант выполняет очистку перед сборкой. Эта очистка увеличивает время работы, поскольку она удаляет ссылки, которые можно использовать.
    • Воспользуйтесь тем, что симулятор не требует применять песочницу. Включение в проект больших ресурсов, таких как видео, вынуждает применять длительное копирование файлов при каждом запуске приложения в симуляторе. Старайтесь избегать таких затратных операций, например размещайте большие файлы в корневом каталоге и указывайте в приложении ссылки на них в виде полного пути к файлу.
    • Если вы сомневаетесь, используйте флаг --time --time для оценки изменений

На снимке экрана ниже показано, как задавать эти параметры симулятора в параметрах iOS.

Screenshot shows Project Options, including Linker behavior, Additional mtouch arguments, and Optimize P N G images.

Рекомендации для устройства

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

Конфигурации сборки

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

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

Также важно понимать взаимосвязь между сборкой и развертыванием. Время развертывания напрямую зависит от размера приложения. Чем крупнее приложение, тем больше времени нужно для его развертывания. Уменьшая размер приложения, вы сможете уменьшить время развертывания.

Но одновременно с уменьшением размера приложения может снижаться и время сборки. Это связано с тем, что удаление кода из приложения занимает меньше времени, чем компиляция в машинный код тех фрагментов, которые не будут использоваться. Уменьшение объектных файлов ускоряет компоновку, а также позволяет создать исполняемый файл меньшего размера благодаря уменьшению числа создаваемых символов. Таким образом, снижение размера окупается дважды. По этой простой причине для всех сборок для устройства по умолчанию применяется вариант Компоновать SDK.

Примечание.

Параметр Компоновать SDK может выглядеть в вашей среде разработки как "Компоновать только пакеты SDK" или "Компоновать только сборки SDK" и т. п.

Советы

  • Построить:
    • Сборка для одной архитектуры (например, ARM64) выполняется быстрее, чем сборка толстого двоичного файла (например, для ARMv7 и ARM64).
    • Избегайте оптимизации PNG-файлов на этапе отладки.
    • Попробуйте использовать компоновку для всех сборок. Оптимизируйте все сборки.
    • Отключите создание отладочных символов с помощью --dsym=false. Но не забывайте, что их отключение означает, что в отчетах о сбоях символы будут создаваться только на том компьютере, где выполнялась сборка приложения, и только в том случае, если для приложения не удалялись лишние компоненты.

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

  • Толстые двоичные файлы (для отладки).
  • Отключение компоновщика --nolink.
  • Отключение полоски
    • Символы --nosymbolstrip.
    • IL (для выпуска) --nostrip.

Дополнительные советы

  • Как и в симуляторе, предпочитайте сборку над перестроениями
    • Сборки AOT (объектные файлы) сохраняются в кэше сборок.
  • Отладочные построения занимают больше времени из-за применения символов и dsymutil, а также из-за большего размера файлов и, следовательно, увеличения времени на их загрузку.
  • Сборка выпуска по умолчанию удаляет IL из сборок. Это занимает очень мало времени и часто полностью оправдано благодаря снижению размера APP-файла для развертывания на устройстве.
  • Избегайте развертывания больших статических файлов в каждой сборке (отладка)
    • Использование UIFileSharingEnabled (info.plist)
      • Ресурсы можно отправлять однократно.
  • Если вы сомневаетесь, используйте флаг --time --time для оценки изменений

На снимке экрана ниже показано, как задавать эти параметры симулятора в параметрах iOS.

Screenshot shows Project Options, including Linker behavior, Supported architectures, and other settings.

Использование компоновщика

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

При использовании компоновщика учтите следующие аспекты.

  • Если для устройства выбрать Не компоновать, сборка займет больше времени и создаст приложение большего размера.
    • Apple отклоняет приложения, размер которых превышает установленное ограничение. В зависимости от MinimumOSVersion ограничение может быть всего 60 МБ.
    • Сюда включается и исполняемый файл в машинном коде.
    • Вариант "Не компоновать" работает быстрее при сборке для симулятора, поскольку в нем применяется JIT-компиляция (в отличие от AOT на устройстве).
  • По умолчанию используется вариант "Компоновать SDK".
  • Вариант "Компоновать все" иногда небезопасен, особенно если вы используете не только собственный код, а например NuGets или Components. Если вы откажетесь от компоновки сборок, весь код этих служб будет включен в ваше приложение, что может значительно увеличить его размер.
    • Но если вы выберете Компоновать все, работа приложения может завершиться сбоем. Такой сценарий еще более вероятен, если оно использует внешние компоненты. Это связано с тем, что некоторые компоненты используют отражения для определенных типов.
    • Статический анализ несовместим с применением отражений.

Вы можете применить атрибут [Preserve], чтобы сохранять нужные фрагменты кода в приложении.

Если у вас нет доступа к исходному коду или код создается с помощью автоматических средств, изменение которых нежелательно, защиту от удаления можно обеспечить с помощью XML-файла с полным списком сохраняемых типов и членов. Создав такой файл, добавьте в параметры проекта флаг --xml={file.name}.xml, и тогда код будет обрабатываться так же, как если бы вы использовали атрибуты.

Частичная компоновка приложений

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

  • Используйте Link All, чтобы пропустить некоторые сборки.

    • Это приведет к некоторому увеличению размера приложения.
    • Для этого не нужен доступ к исходному коду.
    • Например --linkall --linkskip=fieldserviceiOS.
  • Использование Link SDK параметра и использование атрибута [LinkerSafe] в необходимых сборках

    • Для этого нужен доступ к исходному коду.
    • Так вы сообщите системе, что для сборки можно безопасно применять компоновку, и она будет обработана так же, как и Xamarin SDK.

Objective-C Bindings

  • Применив для привязок атрибут [Assembly: LinkerSafe], вы можете уменьшить время сборки и размер файла.

  • SmartLink

    • Выполняется для машинного кода.
    • Используйте атрибут [LinkWith (SmartLink=true)].
    • Это помогает компоновщику машинного кода удалять фрагменты из библиотеки, на которую вы указали ссылку.
    • Обратите внимание, что в этом случае не будет работать динамическая подстановка символов.

Итоги

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