Почему Swift компилируется так медленно?


210

Я использую 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

Все еще никакого улучшения вообще. Это начинает становиться смешным. Из-за отсутствия #importSwift я действительно не понимаю, как 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 с разработчиками по этому вопросу время от времени)

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

  1. Добавить HEADER_MAP_USES_VFSнастройки проекта вtrue
  2. Отключить Find implicit dependenciesот вашей схемы
  3. Создайте новый проект и переместите иерархию файлов в новый.

Я попробую решение 3, но решение 1/2 у нас не сработало.

Что забавно во всей этой ситуации, так это то, что, глядя на первый пост по этой проблеме, мы использовали Xcode 6 с кодом, как мне кажется, swift 1 или swift 1.1, когда мы достигли вялости первых компиляций, а теперь, спустя два года, несмотря на реальные улучшения Apple, Ситуация такая же плохая, как и в Xcode 6. Как иронично.

Я действительно ДЕЙСТВИТЕЛЬНО сожалею о том, что выбрал Swift вместо Obj / C для нашего проекта из-за ежедневного разочарования, которое оно вызывает. (Я даже переключаюсь на AppCode, но это другая история)

В любом случае, я вижу, что это ТАКОЕ сообщение имеет 32 000+ просмотров и 143 повышения на момент написания этой статьи, так что, думаю, я не единственный. Держитесь, ребята, несмотря на пессимизм по поводу этой ситуации, в конце туннеля может быть немного света.

Если у вас есть время (и смелость!), Думаю, Apple приветствует радар по этому поводу.

До следующего раза! ура

ОБНОВЛЕНИЕ с Xcode 9

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

введите описание изображения здесь

Уже попробовали, но обновите этот пост после того, как это будет сделано. Выглядит многообещающе, хотя.


1
Интересный! Интересно, это просто отсутствующая оптимизация или необходимость разбора такого количества файлов, так как нет файлов интерфейса.
Zaph

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

4
Компиляция стала невероятно медленной в моем проекте, начиная с XCode 6 beta 6. Где я не уверен, связано ли это с изменениями в бета-версии или из-за моего кода. Но мой проект еще не большой (~ 40-50 файлов Swift).
БадминтонКат

2
Компиляция стала невыносимо медленной по мере роста моего проекта. Я также зависим от нескольких стручков, которые, я уверен, раздражают проблему. Это использует недавний не бета-релиз.
Энди

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

Ответы:


70

Что ж, оказалось, что Роб Нейпир был прав. Это был один единственный файл (фактически один метод), который заставлял компилятор работать с ошибками.

Не поймите меня неправильно. Swift перекомпилирует все ваши файлы каждый раз, но самое замечательное то, что Apple добавила обратную связь компиляции в режиме реального времени по файлам, которые она компилирует, поэтому Xcode 6 GM теперь показывает, какие файлы Swift компилируются, и статус компиляции в режиме реального времени. как вы можете видеть на этом скриншоте:

Введите описание изображения здесь

Так что это очень удобно, чтобы узнать, какой из ваших файлов занимает так много времени. В моем случае это был кусок кода:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : self.title ?? ""
        ])

return dic.copy() as NSDictionary

потому что собственность titleбыла типа var title:String?и нет NSString. Компилятор сходил с ума, добавляя его в NSMutableDictionary.

Меняя это на:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : NSString(string: self.title ?? "")
        ])

return dic.copy() as NSDictionary

заставил компиляцию идти от 10/15 секунд (может быть, даже больше) до одной секунды ... удивительно.


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

1
Откуда вы взяли это представление @apouche? Я не вижу его в xcode
Eric

2
Вам нужно открыть помощник по отладке (CMD + 8) и нажать на текущую сборку
apouche

1
да, я уверен, что Apple оптимизирует это позже, в противном случае выполнение реальных проектов в быстрой версии обречено прямо здесь и там.
apouche

1
Как я могу получить к этому инструменту, который показывает, какие файлы компилируются?
jgvb

42

Мы попробовали немало вещей для борьбы с этим, поскольку у нас есть около 100 тыс. Строк кода Swift и 300 тыс. Строк кода ObjC.

Нашим первым шагом была оптимизация всех функций в соответствии с выводом времени компиляции функции (например, как описано здесь https://thatthinginswift.com/debug-long-compile-times-swift/ )

Затем мы написали скрипт для объединения всех файлов swift в один файл, это нарушает уровни доступа, но это привело к увеличению времени компиляции с 5-6 минут до ~ 1 минуты.

Теперь это несущественно, потому что мы спросили об этом Apple, и они посоветовали нам сделать следующее:

  1. Включите «оптимизацию всего модуля» в настройке сборки «Swift Compiler - Code Generation». Выбрать'Fast, Whole Module Optimization'

введите описание изображения здесь

  1. В 'Swift Compiler - Custom Flags' для ваших разработок добавьте '-Onone'

введите описание изображения здесь введите описание изображения здесь

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

Для получения дополнительной информации об оптимизации всего модуля, проверьте блог в блоге Apple здесь - https://swift.org/blog/whole-module-optimizations/

Мы обнаружили, что эти настройки позволяют скомпилировать наш код Swift за 30 секунд :-) У меня нет доказательств того, как он будет работать в других проектах, но я предлагаю попробовать, если время компиляции Swift все еще остается для вас проблемой.

Обратите внимание, что для ваших сборок в App Store вы должны оставить '-Onone'флажок, так как оптимизация рекомендуется для производственных сборок.


4
Большое спасибо за этот совет! Я просто не понимаю, почему в официальных источниках ничего подобного нет (по крайней мере, легко найти), например, в статье, о которой вы упоминаете, должно (обязательно!) Быть замечание -Onone. Мы пока не можем использовать оптимизацию всего модуля, потому что это приводит к сбою компилятора ... Но ваш совет дает почти х10-кратное увеличение нашей скорости сборки. На MacBook Air (ежегодно 2013 г.) он собирался примерно за 8 минут, а теперь он занимает примерно 1 минуту, а половина времени тратится на переключение между целями (у нас есть приложения, расширения и несколько собственных фреймворков) и сборкой раскадровок
Илья Пучка

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

Работай с моим тоже. Использование -Ononeсправки для сокращения времени сборки. Спасибо большое, приятель!
nahung89

34

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

В качестве примера кода, который может вызвать проблемы, эта 38-строчная суть занимает более минуты для компиляции в бета-версии 7. Все это вызвано этим одним блоком:

let pipeResult =
seq |> filter~~ { $0 % 2 == 0 }
  |> sorted~~ { $1 < $0 }
  |> map~~ { $0.description }
  |> joinedWithCommas

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


Я не уверен, что вы видели мой комментарий относительно CompileSwiftфазы. Требуются все быстрые файлы, даже если был изменен только один. Так что если это один файл, который занимает некоторое время (в чем я сильно сомневаюсь), компилятор никогда не скажет вам, какой это файл.
Апрель

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

Я прошу прощения за то, что не дал вам щедрость, потому что сначала не верю. Я также пытался скомпилировать файлы один за другим, но это было громоздко (приходилось правильно давать фреймворки и deps каждый раз), поэтому я сдался. Пожалуйста, смотрите мой последний ответ на этот пост для полного объяснения
apouche

Я не думаю, что это основано на размере проекта. Мой проект имеет только 4 быстрых файла и неожиданно начал компилировать невероятно медленно. Вчера было светло быстро. Не могу указать на то, что я сделал с моим проектом, в частности, кроме добавления значка и запуска изображений.
Трэвис М.

33

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

Следует отметить, что по умолчанию он создает 2 файла одновременно для каждого ядра ЦП и не даст вам «чистого» истекшего времени, а абсолютного «пользовательского» времени. Таким образом, все временные интервалы распределяются между распараллеленными файлами и выглядят очень похоже.

Чтобы преодолеть это, установите -jobsфлаг в 1 , чтобы он не распараллеливал сборки файлов. Это займет больше времени, но в итоге у вас будет «чистое» время компиляции, которое вы можете сравнить файл за файлом.

Это пример команды, которая должна сделать свое дело:

xctool -workspace <your_workspace> -scheme <your_scheme> -jobs 1 build

Вывод фазы «Compile Swift files» будет выглядеть примерно так:

...Compile EntityObserver.swift (1623 ms)Compile Session.swift (1526 ms)Compile SearchComposer.swift (1556 ms)
...

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

ПРИМЕЧАНИЕ: технически вы также можете сделать это, xcodebuildно результат невероятно многословен и труден для использования.


1
Просто убедитесь, что для оптимизации всего модуля вашего проекта установлено значение false, иначе она не будет выделять отдельные файлы swift.
Сэйбс

1
Смотрите Swift CompilerOptimization LevelдляFast, Whole Module Optimization [-O -whole-module-optimization]
Мэтт

27

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

пример

// Build time: 5238.3ms
return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height)

После развертывания опций время сборки сократилось на 99,4% .

// Build time: 32.4ms
var padding: CGFloat = 22
if let rightView = rightView {
    padding += rightView.bounds.width
}

if let leftView = leftView {
    padding += leftView.bounds.width
}
return CGSizeMake(size.width + padding, bounds.height)

Смотрите больше примеров в этом посте и этом посте .

Анализатор времени сборки для Xcode

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

образ

Похоже, что в Swift 3 появятся улучшения, так что, надеюсь, мы увидим, что наш код Swift скомпилируется быстрее.


Круто, надеюсь, я могу дать вам больше, чем +1. Вы верны, и ваш плагин также хорош. Я использовал это, и мое время сборки сокращается, что означает супер быструю разработку, потому что эти опции иногда являются кошмаром и приводят к замедлению работы компилятора.
hardikdevios

Фантастика ! Ваш инструмент мне очень помогает. Спасибо
Фил

Отличный плагин - действительно полезный! Спасибо
365SplendidSuns

@ Роберт Гаммессон, у нас есть какой-нибудь инструмент для кода Objective-C?
Ашок

20

Возможно, мы не можем исправить компилятор Swift, но мы можем исправить наш код!

В компиляторе Swift есть скрытая опция, которая распечатывает точные интервалы времени, которые компилятор использует для компиляции каждой отдельной функции: -Xfrontend -debug-time-function-bodies . Это позволяет нам находить узкие места в нашем коде и значительно сокращать время компиляции.

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

xcodebuild -workspace App.xcworkspace -scheme App clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt

Обалденный Брайан Айрас написал блестящую статью об этом, « Профилируя время компиляции Swift» .


2
Для тех, у кого zsh alias grep='noglob grep'первый, иначе grep не сработает
Хайме Агудо

16

Решение отливка.

У меня было огромное множество тонн словарей, как это:

["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
.....

На его компиляцию ушло около 40 минут. Пока я не отлил словари вот так:

["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
....

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


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

4
Это было бы смешно, если бы не было так грустно.
Том Андерсен

15

Следует отметить, что механизм вывода типов Swift может быть очень медленным с вложенными типами. Вы можете получить общее представление о том, что вызывает медлительность, просмотрев журнал сборки для отдельных модулей компиляции, которые занимают много времени, а затем скопировав и вставив полную порожденную Xcode команду в окно терминала, а затем нажав CTRL- \, чтобы получить немного диагностики. Взгляните на http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times для полного примера.


Это для меня лучший ответ (см. Ссылку). Я мог легко найти две разные строки, которые были проблемой, и решить ее, разложив мои строки на более мелкие строки.
Нико

Это очень полезный ответ, потому что он показывает, как найти сумасшедший компилятор. В моем случае это было следующее: 'curScore [curPlayer% 2] + curScore [2 + curPlayer% 2] == 3 && maker% 2 == curPlayer% 2' Как только я переместил его из 'if' в 'let «это привело к тому, что« выражение было слишком сложным, чтобы его можно было решить за разумное время; рассмотрите возможность разбиения выражения на отдельные подвыражения »
Дмитрий

Это, безусловно, самый полезный способ решить эту проблему.
Ричард Венейбл

9

Также убедитесь, что при компиляции для отладки (либо Swift, либо Objective-C) вы установили только Build Active Architecture:

введите описание изображения здесь


6

Поскольку весь этот материал находится в бета-версии, а компилятор Swift (по крайней мере, на сегодняшний день) не открыт, я думаю, что нет реального ответа на ваш вопрос.

Прежде всего, сравнение Objective-C с компилятором Swift несколько жестоко. Swift все еще в бета-версии, и я уверен, что Apple работает над обеспечением функциональности и исправлением ошибок, а не над молниеносной скоростью (вы не начинаете строить дом, покупая мебель). Я думаю, Apple в свое время оптимизирует компилятор.

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

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

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


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

1
2017 и все еще медленно
Педро Пауло Аморим

2017 с Xcode 9 и новой системой сборки и все еще медленно
pableiros

2018 с Xcode 9, у меня есть проект с 50+ быстрыми файлами, если я делаю чистую сборку, сейчас прошло 5 минут и моя компиляция еще не завершена.
Чен Ли Ён

5

Для Xcode 8 перейдите в настройки проекта, затем «Редактор»> «Добавить параметр сборки»> «Добавить пользовательский параметр» и добавьте следующее:

SWIFT_WHOLE_MODULE_OPTIMIZATION = YES

Добавление этого флага сократило время компиляции чистой сборки с 7 минут до 65 секунд для проекта 40KLOC swift, чудесным образом. Также могу подтвердить, что 2 друга видели подобные улучшения в корпоративных проектах.

Я могу только предположить, что это какая-то ошибка в Xcode 8.0

РЕДАКТИРОВАТЬ: Кажется, он не работает больше в Xcode 8.3 для некоторых людей.


2
Где "настройки проекта", пожалуйста?
Ранийс

@Raniys Нажмите на синий значок в корневом уровне на левой панели в Xcode.
Крис

Я обнаружил, что с Xcode 8.3 (не бета) это больше не работает в моем случае :(
Крис

4

К сожалению, компилятор 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/

  • Облегчите механизм быстрого вывода типа, дав несколько подсказок с явными приведениями.


4

Конструкция быстрых массивов и словарей, кажется, довольно популярная причина для этого (особенно для тех, кто имеет опыт работы с Ruby ), то есть

var a = ["a": "b",
         "c": "d",
         "e": "f",
         "g": "h",
         "i": "j",
         "k": "l",
         "m": "n",
         "o": "p",
         "q": "r",
         "s": "t",
         "u": "v",
         "x": "z"]

вероятно, будет причиной, по которой это следует исправить:

var a = NSMutableDictionary()
a["a"] = "b"
a["c"] = "d"
... and so on

4

Для отладки и тестирования обязательно используйте следующие параметры, чтобы сократить время компиляции с примерно 20 минут до менее чем 2 минут,

  1. В настройках сборки проекта выполните поиск по запросу «Оптимизация». Установите параметр «Отладка» на «Самый быстрый [-O3]» или выше.
  2. Установить сборку для активной архитектуры: ДА
  3. Формат отладочной информации: DWARF
  4. Оптимизация всего модуля: НЕТ

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

Но убедитесь, что вы, по крайней мере, установили «DWARF с dSYM» (если вы хотите отслеживать свое приложение) и «Построить активную архитектуру» на «НЕТ» для выпуска / архивации, чтобы отправить его в iTunes Connect (я тоже помню, что здесь я тоже потратил несколько часов).


4
Я могу ошибаться, но не приведет ли увеличение уровней оптимизации к увеличению времени сборки? Уровни оптимизации улучшат производительность во время выполнения.
Водопад Майкл

1
Set Build for Active Architecture: YESдал мне примерно 45% сокращение времени компиляции. Большое спасибо.
Жан Ле Мойнан

4

Компилятор тратит много времени на вывод и проверку типов. Поэтому добавление аннотаций типов очень помогает компилятору.

Если у вас много связанных вызовов функций, таких как

let sum = [1,2,3].map({String($0)}).flatMap({Float($0)}).reduce(0, combine: +)

Затем компилятору требуется время, чтобы выяснить, какой тип sumдолжен быть. Добавление типа помогает. То, что также помогает, тянет прерывистые шаги в отдельные переменные.

let numbers: [Int] = [1,2,3]
let strings: [String] = sum.map({String($0)})
let floats: [Float] = strings.flatMap({Float($0)})
let sum: Float = floats.reduce(0, combine: +)

Особенно для числовых типов CGFloat, Intэто может сильно помочь. Буквенное число наподобие 2может представлять множество различных числовых типов. Таким образом, компилятор должен выяснить из контекста, какой он есть.

+Также следует избегать функций, на поиск которых уходит много времени . Использование нескольких +для объединения нескольких массивов является медленным, потому что компилятору необходимо выяснить, какая реализация +должна вызываться для каждого +. Поэтому использовать var a: [Foo]с append()вместо этого , если это возможно.

Вы можете добавить предупреждение, чтобы определить, какие функции медленно компилируются в XCode .

В настройках сборки для вашей цели найдите другие флаги Swift и добавьте

-Xfrontend -warn-long-function-bodies=100

предупреждать для каждой функции, которая компилируется дольше 100 мс.


4

Для проектов , которые смешиваются Objective-C и Swift код, мы можем установить -enable-bridging-pchв Other Swift Flags. При этом заголовок моста анализируется только один раз, и результат (временный «предварительно скомпилированный заголовок» или файл «PCH») кэшируется и повторно используется во всех файлах Swift в целевом объекте. Apple заявила, что сокращает время сборки на 30%.Ссылка Ссылка:

ПРИМЕЧАНИЕ. Это работает только для Swift 3.1 и выше.


2

Перезагрузка моего Mac сделала чудеса для этой проблемы. Я перешел с 15-минутных сборок на 30-секундные, просто перезагрузившись.


1

Быстрое время компиляции было улучшено в новом Xcode 6.3

Улучшения компилятора

Компилятор Swift 1.2 был разработан, чтобы быть более стабильным и улучшать производительность во всех отношениях. Эти изменения также обеспечивают лучший опыт при работе с Swift в Xcode. Некоторые из наиболее заметных улучшений включают в себя:

Инкрементные сборки

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

Быстрее исполняемые файлы

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

Лучшая диагностика компилятора

Более четкие сообщения об ошибках и предупреждения вместе с новым Fix-it облегчают написание правильного кода Swift 1.2.

Улучшения стабильности

Наиболее распространенные ошибки компилятора были исправлены. Вы также должны видеть меньше предупреждений SourceKit в редакторе Xcode.


0

Вот еще один случай, который может вызвать значительное замедление с выводом типа. Объединение операторов .

Изменение строки, как:

abs(some_optional_variable ?? 0)

в

abs((some_optional_variable ?? 0) as VARIABLE_TYPE)

помог перенести время компиляции с 70 на 13


0

У меня ничего не получалось в Xcode 6.3.1 - когда я добавил около 100 файлов Swift, Xcode случайно зависал при сборке и / или индексации. Я попробовал модульный вариант без успеха.

Установка и использование Xcode 6.4 Beta фактически работали для меня.


0

Это работает как по волшебству для меня - Ускорение Swift Компиляция . Это уменьшило время компиляции до 3 минут с 10 минут.

Он говорит , что вы должны включить на Whole Module Optimizationвремя добавления -Ononeв Other Swift Flags.

Я использую Swift 3на Xcode 8.3/Xcode 8.2 .


0

Смешивание целочисленного литерала и плавающего литерала в одном выражении также приводит к длительному времени компиляции.

1.0 + (1.0 + (1  * (1.0 + 1.0))) // 3429ms

1.0 + (1.0 + (1.0  * (1.0 + 1.0))) // 5ms

Многие выражения времени компиляции 1000+ мс сокращаются до 10 ~ 100 мс после того, как я вставил .0литерал после целого числа.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.