Я использую Xcode 6 Beta 6.
Это то, что беспокоило меня в течение некоторого времени, но сейчас оно достигло точки, когда его едва ли можно использовать.
Мой проект начинает иметь приличный размер 65 Swift-файлов и несколько мостовых файлов Objective-C (которые на самом деле не являются причиной проблемы).
Кажется, что любое небольшое изменение любого файла Swift (например, добавление простого пробела в классе, который едва используется в приложении) приведет к перекомпиляции всех файлов Swift для указанной цели.
После более глубокого исследования я обнаружил, что то, что занимает почти 100% времени компилятора, - это CompileSwift
фаза, когда XCode запускает swiftc
команду для всех файлов Swift вашей цели.
Я провел дальнейшее исследование, и если я оставлю делегат приложения только с контроллером по умолчанию, компиляция будет очень быстрой, но, поскольку я добавлял все больше и больше файлов моего проекта, время компиляции стало очень медленным.
Теперь, имея только 65 исходных файлов, каждый раз для компиляции требуется около 8/10 секунд. Не очень быстро .
Я не видел ни одного поста, рассказывающего об этой проблеме, кроме этой , но это была старая версия Xcode 6. Поэтому мне интересно, единственный ли я в этом случае.
ОБНОВИТЬ
Я проверил несколько проектов Swift на GitHub, таких как Alamofire , Euler и CryptoSwift , но ни у одного из них не было достаточно файлов Swift для сравнения. Единственный проект, который я нашел, у которого был приличный размер, был SwiftHN , и, хотя в нем было всего дюжина исходных файлов, я все еще мог проверить одно и то же, один простой пробел и весь проект нуждался в перекомпиляции, которая начинала принимать мало времени (2/3 секунды).
По сравнению с кодом Objective-C, где анализатор и компиляция работают быстро, на самом деле кажется, что Swift никогда не сможет обрабатывать большие проекты, но, пожалуйста, скажите, что я ошибаюсь.
ОБНОВЛЕНИЕ с Xcode 6 Beta 7
Все еще никакого улучшения вообще. Это начинает становиться смешным. Из-за отсутствия #import
Swift я действительно не понимаю, как Apple сможет когда-либо оптимизировать это.
ОБНОВЛЕНИЕ С Xcode 6.3 и Swift 1.2
Apple добавила инкрементные сборки (и многие другие оптимизации компилятора). Вы должны перенести свой код в Swift 1.2, чтобы увидеть эти преимущества, но Apple добавила инструмент в Xcode 6.3, чтобы помочь вам сделать это:
ТЕМ НЕ МЕНИЕ
Не радуйся так быстро, как я. Решатель графиков, который они используют для создания инкрементальной сборки, еще не очень хорошо оптимизирован.
Действительно, во-первых, он не рассматривает изменения сигнатур функций, поэтому, если вы добавите пробел в блок одного метода, все файлы, зависящие от этого класса, будут перекомпилированы.
Во-вторых, создается дерево на основе файлов, которые были перекомпилированы, даже если изменение не влияет на них. Например, если вы переместите эти три класса в разные файлы
class FileA: NSObject {
var foo:String?
}
class FileB: NSObject {
var bar:FileA?
}
class FileC: NSObject {
var baz:FileB?
}
Теперь, если вы измените FileA
, компилятор, очевидно, пометит FileA
для перекомпиляции. Он также будет перекомпилирован FileB
(это будет нормально на основе изменений в FileA
), но также FileC
потому, что FileB
он перекомпилирован, и это довольно плохо, потому что здесь FileC
никогда не используется FileA
.
Поэтому я надеюсь, что они улучшат этот решатель дерева зависимостей ... Я открыл радар с этим примером кода.
ОБНОВЛЕНИЕ С Xcode 7 beta 5 и Swift 2.0
Вчера Apple выпустила бета-версию 5, и внутри заметок о выпуске мы могли видеть:
Swift Language & Compiler • Инкрементные сборки: изменение только тела функции больше не должно приводить к перестроению зависимых файлов. (15352929)
Я дал ему попробовать, и я должен сказать, что он работает очень (очень!) Хорошо сейчас. Они значительно оптимизировали инкрементные сборки в swift.
Я настоятельно рекомендую вам создать swift2.0
ветку и поддерживать ваш код в актуальном состоянии, используя XCode 7 beta 5. Вы будете довольны улучшениями компилятора (однако я бы сказал, что глобальное состояние XCode 7 все еще медленное и глючное)
ОБНОВЛЕНИЕ С Xcode 8.2
Прошло много времени с момента моего последнего обновления по этому вопросу, так что вот оно.
Наше приложение теперь содержит около 20 тыс. Строк почти исключительно кода Swift, что является достойным, но не выдающимся. Он прошел быструю миграцию 2 и 3. Компиляция MacBook Pro середины 2014 года (Intel Core i7 с частотой 2,5 ГГц, 2,5 ГГц) занимает около 5/6 м, что вполне приемлемо для чистой сборки.
Однако инкрементная сборка все еще шутка, несмотря на то, что Apple утверждает, что:
Xcode не будет перестраивать всю цель, когда произошли только небольшие изменения. (28892475)
Очевидно, я думаю, что многие из нас просто смеялись после проверки этой чепухи (добавление одного частного (private!) Свойства в любой файл моего проекта перекомпилирует все это ...)
Я хотел бы указать вам, ребята, на эту ветку на форумах разработчиков Apple, на которой есть еще немного информации об этой проблеме (а также высоко ценить связь Apple с разработчиками по этому вопросу время от времени)
В основном люди придумали несколько вещей, чтобы попытаться улучшить инкрементную сборку:
- Добавить
HEADER_MAP_USES_VFS
настройки проекта вtrue
- Отключить
Find implicit dependencies
от вашей схемы - Создайте новый проект и переместите иерархию файлов в новый.
Я попробую решение 3, но решение 1/2 у нас не сработало.
Что забавно во всей этой ситуации, так это то, что, глядя на первый пост по этой проблеме, мы использовали Xcode 6 с кодом, как мне кажется, swift 1 или swift 1.1, когда мы достигли вялости первых компиляций, а теперь, спустя два года, несмотря на реальные улучшения Apple, Ситуация такая же плохая, как и в Xcode 6. Как иронично.
Я действительно ДЕЙСТВИТЕЛЬНО сожалею о том, что выбрал Swift вместо Obj / C для нашего проекта из-за ежедневного разочарования, которое оно вызывает. (Я даже переключаюсь на AppCode, но это другая история)
В любом случае, я вижу, что это ТАКОЕ сообщение имеет 32 000+ просмотров и 143 повышения на момент написания этой статьи, так что, думаю, я не единственный. Держитесь, ребята, несмотря на пессимизм по поводу этой ситуации, в конце туннеля может быть немного света.
Если у вас есть время (и смелость!), Думаю, Apple приветствует радар по этому поводу.
До следующего раза! ура
ОБНОВЛЕНИЕ с Xcode 9
Наткнуться на это сегодня. XCode незаметно представил новую систему сборки для улучшения текущей ужасной производительности. Вы должны включить его через настройки рабочего пространства.
Уже попробовали, но обновите этот пост после того, как это будет сделано. Выглядит многообещающе, хотя.
Ответы:
Что ж, оказалось, что Роб Нейпир был прав. Это был один единственный файл (фактически один метод), который заставлял компилятор работать с ошибками.
Не поймите меня неправильно. Swift перекомпилирует все ваши файлы каждый раз, но самое замечательное то, что Apple добавила обратную связь компиляции в режиме реального времени по файлам, которые она компилирует, поэтому Xcode 6 GM теперь показывает, какие файлы Swift компилируются, и статус компиляции в режиме реального времени. как вы можете видеть на этом скриншоте:
Так что это очень удобно, чтобы узнать, какой из ваших файлов занимает так много времени. В моем случае это был кусок кода:
потому что собственность
title
была типаvar title:String?
и нетNSString
. Компилятор сходил с ума, добавляя его вNSMutableDictionary
.Меняя это на:
заставил компиляцию идти от 10/15 секунд (может быть, даже больше) до одной секунды ... удивительно.
источник
Мы попробовали немало вещей для борьбы с этим, поскольку у нас есть около 100 тыс. Строк кода Swift и 300 тыс. Строк кода ObjC.
Нашим первым шагом была оптимизация всех функций в соответствии с выводом времени компиляции функции (например, как описано здесь https://thatthinginswift.com/debug-long-compile-times-swift/ )
Затем мы написали скрипт для объединения всех файлов swift в один файл, это нарушает уровни доступа, но это привело к увеличению времени компиляции с 5-6 минут до ~ 1 минуты.
Теперь это несущественно, потому что мы спросили об этом Apple, и они посоветовали нам сделать следующее:
'Fast, Whole Module Optimization'
'-Onone'
Когда эти флаги установлены, компилятор скомпилирует все файлы Swift за один шаг. Мы обнаружили, что с помощью скрипта слияния это намного быстрее, чем индивидуальная компиляция файлов. Однако без
-Onone'
переопределения он также оптимизирует весь модуль, что медленнее. Когда мы устанавливаем'-Onone'
флаг в другие флаги Swift, он останавливает оптимизацию, но не останавливает компиляцию всех файлов Swift за один шаг.Для получения дополнительной информации об оптимизации всего модуля, проверьте блог в блоге Apple здесь - https://swift.org/blog/whole-module-optimizations/
Мы обнаружили, что эти настройки позволяют скомпилировать наш код Swift за 30 секунд :-) У меня нет доказательств того, как он будет работать в других проектах, но я предлагаю попробовать, если время компиляции Swift все еще остается для вас проблемой.
Обратите внимание, что для ваших сборок в App Store вы должны оставить
'-Onone'
флажок, так как оптимизация рекомендуется для производственных сборок.источник
-Onone
. Мы пока не можем использовать оптимизацию всего модуля, потому что это приводит к сбою компилятора ... Но ваш совет дает почти х10-кратное увеличение нашей скорости сборки. На MacBook Air (ежегодно 2013 г.) он собирался примерно за 8 минут, а теперь он занимает примерно 1 минуту, а половина времени тратится на переключение между целями (у нас есть приложения, расширения и несколько собственных фреймворков) и сборкой раскадровок-Onone
справки для сокращения времени сборки. Спасибо большое, приятель!Вероятно, это имеет мало общего с размером вашего проекта. Это, вероятно, какой-то определенный фрагмент кода, возможно, даже одна строка. Вы можете проверить это, пытаясь скомпилировать один файл за раз, а не весь проект. Или попробуйте просмотреть журналы сборки, чтобы увидеть, какой файл занимает так много времени.
В качестве примера кода, который может вызвать проблемы, эта 38-строчная суть занимает более минуты для компиляции в бета-версии 7. Все это вызвано этим одним блоком:
Упростите это всего на одну или две строки, и он будет компилироваться практически мгновенно. Проблема в том, что это вызывает экспоненциальный рост (возможно, факторный рост) компилятора. Очевидно, что это не идеально, и если вы можете изолировать такие ситуации, вы должны открыть радары, чтобы помочь устранить эти проблемы.
источник
CompileSwift
фазы. Требуются все быстрые файлы, даже если был изменен только один. Так что если это один файл, который занимает некоторое время (в чем я сильно сомневаюсь), компилятор никогда не скажет вам, какой это файл.swiftc
чтобы увидеть, сколько времени они занимают.Если вы пытаетесь определить конкретные файлы, которые замедляют ваше время компиляции, вы можете попробовать скомпилировать его из командной строки с помощью xctool, что даст вам время компиляции файл за файлом.
Следует отметить, что по умолчанию он создает 2 файла одновременно для каждого ядра ЦП и не даст вам «чистого» истекшего времени, а абсолютного «пользовательского» времени. Таким образом, все временные интервалы распределяются между распараллеленными файлами и выглядят очень похоже.
Чтобы преодолеть это, установите
-jobs
флаг в 1 , чтобы он не распараллеливал сборки файлов. Это займет больше времени, но в итоге у вас будет «чистое» время компиляции, которое вы можете сравнить файл за файлом.Это пример команды, которая должна сделать свое дело:
xctool -workspace <your_workspace> -scheme <your_scheme> -jobs 1 build
Вывод фазы «Compile Swift files» будет выглядеть примерно так:
Из этого вывода вы можете быстро определить, какие файлы занимают больше времени, чем другие, для компиляции. Кроме того, вы можете с высокой точностью определить, уменьшают ли ваши рефакторинги (явное приведение, подсказки типов и т. Д.) Время компиляции для определенных файлов или нет.
ПРИМЕЧАНИЕ: технически вы также можете сделать это,
xcodebuild
но результат невероятно многословен и труден для использования.источник
Swift Compiler
→Optimization Level
дляFast, Whole Module Optimization [-O -whole-module-optimization]
В моем случае Xcode 7 вообще ничего не изменил. У меня было несколько функций, требующих несколько секунд для компиляции.
пример
После развертывания опций время сборки сократилось на 99,4% .
Смотрите больше примеров в этом посте и этом посте .
Анализатор времени сборки для Xcode
Я разработал плагин Xcode, который может пригодиться всем, кто сталкивается с такими проблемами.
Похоже, что в Swift 3 появятся улучшения, так что, надеюсь, мы увидим, что наш код Swift скомпилируется быстрее.
источник
Возможно, мы не можем исправить компилятор Swift, но мы можем исправить наш код!
В компиляторе Swift есть скрытая опция, которая распечатывает точные интервалы времени, которые компилятор использует для компиляции каждой отдельной функции:
-Xfrontend -debug-time-function-bodies
. Это позволяет нам находить узкие места в нашем коде и значительно сокращать время компиляции.Просто запустите следующее в терминале и проанализируйте результаты:
Обалденный Брайан Айрас написал блестящую статью об этом, « Профилируя время компиляции Swift» .
источник
alias grep='noglob grep'
первый, иначе grep не сработаетРешение отливка.
У меня было огромное множество тонн словарей, как это:
На его компиляцию ушло около 40 минут. Пока я не отлил словари вот так:
Это работало практически для любой проблемы, с которой я столкнулся в отношении типов данных, которые я жестко запрограммировал в своем приложении.
источник
Следует отметить, что механизм вывода типов Swift может быть очень медленным с вложенными типами. Вы можете получить общее представление о том, что вызывает медлительность, просмотрев журнал сборки для отдельных модулей компиляции, которые занимают много времени, а затем скопировав и вставив полную порожденную Xcode команду в окно терминала, а затем нажав CTRL- \, чтобы получить немного диагностики. Взгляните на http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times для полного примера.
источник
Также убедитесь, что при компиляции для отладки (либо Swift, либо Objective-C) вы установили только Build Active Architecture:
источник
Поскольку весь этот материал находится в бета-версии, а компилятор Swift (по крайней мере, на сегодняшний день) не открыт, я думаю, что нет реального ответа на ваш вопрос.
Прежде всего, сравнение Objective-C с компилятором Swift несколько жестоко. Swift все еще в бета-версии, и я уверен, что Apple работает над обеспечением функциональности и исправлением ошибок, а не над молниеносной скоростью (вы не начинаете строить дом, покупая мебель). Я думаю, Apple в свое время оптимизирует компилятор.
Если по какой-то причине все исходные файлы должны быть скомпилированы полностью, можно создать отдельные модули / библиотеки. Но эта опция пока невозможна, так как Swift не может разрешать библиотеки до тех пор, пока язык не станет стабильным.
Я думаю, что они будут оптимизировать компилятор. По той же причине, по которой мы не можем создавать предварительно скомпилированные модули, вполне может быть, что компилятору нужно скомпилировать все с нуля. Но как только язык достигнет стабильной версии и формат двоичных файлов больше не меняется, мы сможем создавать наши библиотеки, и, возможно, (?) Компилятор также сможет оптимизировать его работу.
Просто догадываюсь, потому что только Apple знает ...
источник
Для Xcode 8 перейдите в настройки проекта, затем «Редактор»> «Добавить параметр сборки»> «Добавить пользовательский параметр» и добавьте следующее:
Добавление этого флага сократило время компиляции чистой сборки с 7 минут до 65 секунд для проекта 40KLOC swift, чудесным образом. Также могу подтвердить, что 2 друга видели подобные улучшения в корпоративных проектах.
Я могу только предположить, что это какая-то ошибка в Xcode 8.0
РЕДАКТИРОВАТЬ: Кажется, он не работает больше в Xcode 8.3 для некоторых людей.
источник
К сожалению, компилятор Swift все еще не оптимизирован для быстрой и пошаговой компиляции (начиная с бета-версии Xcode 6.3). Тем временем вы можете использовать некоторые из следующих методов для улучшения времени компиляции Swift:
Разделите приложение на Frameworks, чтобы уменьшить влияние перекомпиляции. Но имейте в виду, что вы должны избегать циклических зависимостей в вашем приложении. Для получения дополнительной информации по этой теме проверьте этот пост: http://bits.citrusbyte.com/improving-swift-compile-time/
Используйте Swift для тех частей вашего проекта, которые достаточно стабильны и не меняются часто. Для других областей, где вам нужно часто менять, или областей, требующих выполнения большого количества итераций компиляции / запуска (почти любой материал, связанный с пользовательским интерфейсом), лучше использовать Objective-C с подходом смешивания и сопоставления.
Попробуйте внедрение кода во время выполнения с помощью «Инъекции для Xcode»
Используйте метод roopc: http://roopc.net/posts/2014/speeding-up-swift-builds/
Облегчите механизм быстрого вывода типа, дав несколько подсказок с явными приведениями.
источник
Конструкция быстрых массивов и словарей, кажется, довольно популярная причина для этого (особенно для тех, кто имеет опыт работы с Ruby ), то есть
вероятно, будет причиной, по которой это следует исправить:
источник
Для отладки и тестирования обязательно используйте следующие параметры, чтобы сократить время компиляции с примерно 20 минут до менее чем 2 минут,
Я потратил бесчисленные часы, ожидая, пока проект будет построен, только чтобы понять, что мне нужно было внести одно небольшое изменение, и мне пришлось ждать еще целых 30 минут, чтобы протестировать его. Это настройки, которые работали для меня. (Я все еще экспериментирую с настройками)
Но убедитесь, что вы, по крайней мере, установили «DWARF с dSYM» (если вы хотите отслеживать свое приложение) и «Построить активную архитектуру» на «НЕТ» для выпуска / архивации, чтобы отправить его в iTunes Connect (я тоже помню, что здесь я тоже потратил несколько часов).
источник
Set Build for Active Architecture: YES
дал мне примерно 45% сокращение времени компиляции. Большое спасибо.Компилятор тратит много времени на вывод и проверку типов. Поэтому добавление аннотаций типов очень помогает компилятору.
Если у вас много связанных вызовов функций, таких как
Затем компилятору требуется время, чтобы выяснить, какой тип
sum
должен быть. Добавление типа помогает. То, что также помогает, тянет прерывистые шаги в отдельные переменные.Особенно для числовых типов
CGFloat
,Int
это может сильно помочь. Буквенное число наподобие2
может представлять множество различных числовых типов. Таким образом, компилятор должен выяснить из контекста, какой он есть.+
Также следует избегать функций, на поиск которых уходит много времени . Использование нескольких+
для объединения нескольких массивов является медленным, потому что компилятору необходимо выяснить, какая реализация+
должна вызываться для каждого+
. Поэтому использоватьvar a: [Foo]
сappend()
вместо этого , если это возможно.Вы можете добавить предупреждение, чтобы определить, какие функции медленно компилируются в XCode .
В настройках сборки для вашей цели найдите другие флаги Swift и добавьте
-Xfrontend -warn-long-function-bodies=100
предупреждать для каждой функции, которая компилируется дольше 100 мс.
источник
Для проектов , которые смешиваются Objective-C и Swift код, мы можем установить
-enable-bridging-pch
вOther Swift Flags
. При этом заголовок моста анализируется только один раз, и результат (временный «предварительно скомпилированный заголовок» или файл «PCH») кэшируется и повторно используется во всех файлах Swift в целевом объекте. Apple заявила, что сокращает время сборки на 30%.Ссылка Ссылка:ПРИМЕЧАНИЕ. Это работает только для Swift 3.1 и выше.
источник
Перезагрузка моего Mac сделала чудеса для этой проблемы. Я перешел с 15-минутных сборок на 30-секундные, просто перезагрузившись.
источник
Быстрое время компиляции было улучшено в новом Xcode 6.3
источник
Вот еще один случай, который может вызвать значительное замедление с выводом типа. Объединение операторов .
Изменение строки, как:
в
помог перенести время компиляции с 70 на 13
источник
У меня ничего не получалось в Xcode 6.3.1 - когда я добавил около 100 файлов Swift, Xcode случайно зависал при сборке и / или индексации. Я попробовал модульный вариант без успеха.
Установка и использование Xcode 6.4 Beta фактически работали для меня.
источник
Это работает как по волшебству для меня - Ускорение Swift Компиляция . Это уменьшило время компиляции до 3 минут с 10 минут.
Он говорит , что вы должны включить на
Whole Module Optimization
время добавления-Onone
вOther Swift Flags
.Я использую
Swift 3
наXcode 8.3
/Xcode 8.2
.источник
Смешивание целочисленного литерала и плавающего литерала в одном выражении также приводит к длительному времени компиляции.
Многие выражения времени компиляции 1000+ мс сокращаются до 10 ~ 100 мс после того, как я вставил
.0
литерал после целого числа.источник