Perché il tempo di compilazione di Swift è così lento?


210

Sto usando Xcode 6 Beta 6.

Questo è qualcosa che mi infastidisce da un po 'di tempo ormai, ma sta raggiungendo un punto in cui è appena utilizzabile ora.

Il mio progetto sta iniziando ad avere una dimensione decente di 65 file Swift e alcuni file Objective-C con bridge (che in realtà non sono la causa del problema).

Sembra che qualsiasi lieve modifica a qualsiasi file Swift (come l'aggiunta di un semplice spazio bianco in una classe che è appena usata nell'app) causerà la ricompilazione di tutti i file Swift per la destinazione specificata.

Dopo un'indagine più approfondita, ho scoperto che ciò che richiede quasi il 100% del tempo del compilatore è la CompileSwiftfase in cui Xcode esegue il swiftccomando su tutti i file Swift del tuo target.

Ho fatto qualche ulteriore indagine e se mantengo l'app delegata solo con un controller predefinito, la compilazione è molto veloce, ma mentre aggiungevo sempre più file dei miei progetti, il tempo di compilazione stava iniziando a rallentare molto.

Ora con solo 65 file sorgente, ci vogliono circa 8/10 secondi per compilare ogni volta. Non molto veloce .

Non ho visto nessun post parlare di questo problema tranne questo , ma era una vecchia versione di Xcode 6. Quindi mi chiedo se sono l'unico in quel caso.

AGGIORNARE

Ho controllato alcuni progetti Swift su GitHub come Alamofire , Euler e CryptoSwift , ma nessuno di essi aveva abbastanza file Swift per poterlo confrontare. L'unico progetto che ho scoperto che stava iniziando con una dimensione decente era SwiftHN , e anche se aveva solo una dozzina di file sorgente, ero ancora in grado di verificare la stessa cosa, uno spazio semplice e l'intero progetto necessitava di ricompilazione che stava iniziando a prendere un poco tempo (2/3 secondi).

Rispetto al codice Objective-C in cui sia l'analizzatore che la compilation sono velocissimi, sembra davvero che Swift non sarà mai in grado di gestire grandi progetti, ma per favore dimmi che sbaglio.

AGGIORNAMENTO Con Xcode 6 Beta 7

Ancora nessun miglioramento. Questo sta iniziando a diventare ridicolo. Con la mancanza di #importin Swift, non vedo davvero come Apple sarà mai in grado di ottimizzarlo.

AGGIORNAMENTO Con Xcode 6.3 e Swift 1.2

Apple ha aggiunto build incrementali (e molte altre ottimizzazioni del compilatore). Devi migrare il tuo codice su Swift 1.2 per vedere quei vantaggi, ma Apple ha aggiunto uno strumento in Xcode 6.3 per aiutarti a farlo:

Inserisci qui la descrizione dell'immagine

PERÒ

Non rallegrarti troppo velocemente come ho fatto io. Il risolutore di grafici che usano per rendere la build incrementale non è ancora molto ottimizzato.

In effetti, per prima cosa, non esamina le modifiche alla firma della funzione, quindi se aggiungi uno spazio nel blocco di un metodo, tutti i file che dipendono da quella classe verranno ricompilati.

In secondo luogo, sembra creare l'albero in base ai file che sono stati ricompilati anche se una modifica non li influenza. Ad esempio, se si spostano queste tre classi in file diversi

class FileA: NSObject {
    var foo:String?
}
class FileB: NSObject {
    var bar:FileA?
}
class FileC: NSObject {
    var baz:FileB?
}

Ora, se si modifica FileA, il compilatore segnerà ovviamente FileAper essere ricompilato. Si ricompilerà anche FileB(sarebbe OK in base alle modifiche a FileA), ma anche FileCperché FileBè ricompilato, e questo è piuttosto male perché FileCnon lo usa mai FileAqui.

Quindi spero che migliorino quel solutore di alberi delle dipendenze ... Ho aperto un radar con questo codice di esempio.

AGGIORNAMENTO Con Xcode 7 beta 5 e Swift 2.0

Ieri Apple ha rilasciato la beta 5 e all'interno delle note di rilascio abbiamo potuto vedere:

Swift Language & Compiler • Build incrementali: la modifica del solo corpo di una funzione non dovrebbe più comportare la ricostruzione di file dipendenti. (15352929)

Ci ho provato e devo dire che ora funziona davvero (davvero!) Bene. Hanno ottimizzato notevolmente le build incrementali in tempi rapidi.

Consiglio vivamente di creare una swift2.0filiale e mantenere aggiornato il codice utilizzando XCode 7 beta 5. Sarai soddisfatto dei miglioramenti del compilatore (tuttavia direi che lo stato globale di XCode 7 è ancora lento e difettoso)

AGGIORNAMENTO Con Xcode 8.2

È passato un po 'di tempo dal mio ultimo aggiornamento su questo problema, quindi eccolo qui.

La nostra app ora ha circa 20k righe di codice quasi esclusivamente Swift, che è decente ma non eccezionale. Ha subito la migrazione rapida 2 e quindi rapida 3. Ci vogliono circa 5 / 6m per compilare su un Macbook pro metà 2014 (Intel Core i7 a 2,5 GHz) che va bene su una build pulita.

Tuttavia, la build incrementale è ancora uno scherzo nonostante Apple affermi che:

Xcode non ricostruirà un intero target quando si sono verificate solo piccole modifiche. (28892475)

Ovviamente penso che molti di noi abbiano riso dopo aver verificato questa assurdità (l'aggiunta di una proprietà privata (privata!) A qualsiasi file del mio progetto ricompilerà il tutto ...)

Vorrei indicarvi ragazzi su questo thread sui forum degli sviluppatori di Apple che contiene alcune informazioni in più sul problema (oltre ad apprezzare le comunicazioni degli sviluppatori Apple sull'argomento di tanto in tanto)

Fondamentalmente le persone hanno escogitato alcune cose per cercare di migliorare la build incrementale:

  1. Aggiungi un'impostazione di HEADER_MAP_USES_VFSprogetto impostata sutrue
  2. Disabilita Find implicit dependenciesdal tuo schema
  3. Crea un nuovo progetto e sposta la gerarchia dei tuoi file su quello nuovo.

Proverò la soluzione 3 ma la soluzione 1/2 non ha funzionato per noi.

La cosa ironicamente divertente in tutta questa situazione è che guardando il primo post su questo problema stavamo usando Xcode 6 con credo codice swift 1 o swift 1.1 quando abbiamo raggiunto la lentezza delle prime compilation e ora circa due anni dopo, nonostante i reali miglioramenti di Apple, la situazione è tanto grave quanto lo era con Xcode 6. Che ironia.

In realtà mi pento davvero di aver scelto Swift su Obj / C per il nostro progetto a causa della frustrazione quotidiana che comporta. (Passo anche ad AppCode ma questa è un'altra storia)

Ad ogni modo vedo che questo post SO ha 32k + visualizzazioni e 143 up al momento della stesura di questo, quindi credo di non essere l'unico. Resisti ragazzi nonostante sia pessimista per questa situazione, potrebbe esserci un po 'di luce alla fine del tunnel.

Se hai il tempo (e il coraggio!) Immagino che Apple sia contenta del radar su questo.

Alla prossima! Saluti

AGGIORNAMENTO Con Xcode 9

Ci si imbatte in questo oggi. Xcode ha introdotto silenziosamente un nuovo sistema di compilazione per migliorare le orribili prestazioni attuali. Devi abilitarlo attraverso le impostazioni dell'area di lavoro.

inserisci qui la descrizione dell'immagine

Ho ancora provato ma aggiornerà questo post dopo averlo fatto. Sembra promettente però.


1
Interessante! Mi chiedo se si tratti solo di un'ottimizzazione mancante o della necessità di analizzare così tanti file poiché non ci sono file di interfaccia.
zaph,

2
Aveva problemi simili e alla fine mi sono reso conto che era a causa di operatori personalizzati utilizzati nelle classi di entità per deserializzare da JSON. Se ne stai usando qualcuno, ti suggerisco di provare a convertirlo in funzione normale uno per uno e vedere se qualcosa cambia.
Antonio,

4
La compilation è diventata incredibilmente lenta nel mio progetto da XCode 6 beta 6. Dove non sono sicuro se sia dovuto a cambiamenti nella beta o al mio codice. Ma il mio progetto non è ancora grande (~ 40-50 file Swift).
BadmintonCat

2
La compilazione è diventata insopportabilmente lenta con la crescita del mio progetto. Dipendo anche da diversi pod, che sicuramente esasperano il problema. Questo sta usando la recente versione non beta.
Andy,

2
La generazione incrementale viene ancora eseguita in "un'analisi conservativa delle dipendenze, quindi potresti ancora vedere più file da ricostruire di quanto assolutamente necessario." Speriamo che migliorerà nel tempo.
nmdias,

Risposte:


70

Bene, si è scoperto che Rob Napier aveva ragione. Era un singolo file (in realtà un metodo) che stava facendo sì che il compilatore diventasse berzek.

Ora non fraintendermi. Swift ricompila tutti i tuoi file ogni volta, ma la cosa fantastica ora è che Apple ha aggiunto feedback di compilazione in tempo reale sui file che compila, quindi Xcode 6 GM ora mostra quali file Swift vengono compilati e lo stato della compilazione in tempo reale come puoi vedere in questo screenshot:

Inserisci qui la descrizione dell'immagine

Quindi è molto utile sapere quale dei tuoi file impiega così tanto tempo. Nel mio caso era questo pezzo di codice:

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

return dic.copy() as NSDictionary

perché la proprietà titleera di tipo var title:String?e non NSString. Il compilatore stava impazzendo quando lo aggiungeva a NSMutableDictionary.

Modificandolo in:

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

return dic.copy() as NSDictionary

fatto andare la compilation da 10/15 secondi (forse anche di più) fino a un solo secondo ... incredibile.


3
Grazie per aver seguito la risposta. Questo può essere molto utile per gli altri che inseguono lì il motore dell'inferenza del tipo viene impantanato durante la compilazione.
Rob Napier,

1
Dove sei arrivato a questo punto di vista @apouche? Non lo vedo in xcode
Eric,

2
Devi aprire l'assistente di debug (CMD + 8) e fare clic sulla build corrente
apouche,

1
sì, sono sicuro che Apple lo ottimizzerà in seguito, altrimenti fare progetti nel mondo reale in tempi rapidi è destinato proprio qua e là.
apouche,

1
Come posso accedere a questo strumento che mostra quali file vengono compilati?
jgvb,

42

Abbiamo provato parecchie cose per combattere questo dato che abbiamo circa 100k righe di codice Swift e 300k righe di codice ObjC.

Il nostro primo passo è stato quello di ottimizzare tutte le funzioni in base all'output dei tempi di compilazione delle funzioni (ad esempio, come descritto qui https://thatthinginswift.com/debug-long-compile-times-swift/ )

Successivamente abbiamo scritto uno script per unire tutti i file rapidi in un unico file, questo interrompe i livelli di accesso ma ha portato il nostro tempo di compilazione da 5-6 minuti a ~ 1 minuto.

Questo è ora defunto perché abbiamo chiesto a Apple di questo e ci hanno consigliato di fare quanto segue:

  1. Attiva l'ottimizzazione dell'intero modulo nell'impostazione di compilazione "Swift Compiler - Code Generation". Selezionare'Fast, Whole Module Optimization'

inserisci qui la descrizione dell'immagine

  1. In "Swift Compiler - Custom Flags", per le tue build di sviluppo, aggiungi '-Onone'

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Quando vengono impostati questi flag, il compilatore compilerà tutti i file Swift in un solo passaggio. Abbiamo scoperto che con il nostro script di unione questo è molto più veloce della compilazione di file singolarmente. Tuttavia, senza l' -Onone'override, ottimizzerà anche l'intero modulo, che è più lento. Quando impostiamo il '-Onone'flag negli altri flag Swift, interrompe l'ottimizzazione, ma non smette di compilare tutti i file Swift in un solo passaggio.

Per ulteriori informazioni sull'ottimizzazione dell'intero modulo, consulta il post sul blog di Apple qui - https://swift.org/blog/whole-module-optimizations/

Abbiamo scoperto che queste impostazioni consentono la compilazione del nostro codice Swift in 30 secondi :-) Non ho prove di come funzionerebbe su altri progetti, ma suggerisco di provarlo se i tempi di compilazione di Swift sono ancora un problema per te.

Nota per le build del tuo App Store, dovresti lasciare la '-Onone'bandiera fuori, poiché l'ottimizzazione è consigliata per le build di produzione.


4
Grazie mille per questo consiglio! Semplicemente non capisco perché non ci sia nulla di simile in fonti ufficiali (almeno facile da trovare), ad esempio l'articolo che citi dovrebbe (deve!) Avere l'osservazione -Onone. Per il momento non possiamo usare l'ottimizzazione dell'intero modulo perché causa l'arresto anomalo del compilatore ... Ma i tuoi consigli danno quasi x10 alla nostra velocità di compilazione. Su MacBook Air (annuale 2013) stava costruendo circa 8 minuti, ora è sceso a circa 1 minuto e metà del tempo che passa a passare da un obiettivo all'altro (abbiamo app, estensioni e pochi framework interni) e compilare storyboard
Ilya Puchka

Ho anche testato questo metodo ed è solo il metodo menzionato che include il -Onone e riduce significativamente i tempi di costruzione.
Vlad,

Lavora anche con il mio. Utilizzo della guida -Ononeper ridurre i tempi di compilazione. Grazie mille amico!
nahung89,

34

Probabilmente ha poco a che fare con le dimensioni del tuo progetto. Probabilmente è un pezzo di codice specifico, forse anche solo una riga. Puoi provarlo provando a compilare un file alla volta anziché l'intero progetto. Oppure prova a guardare i registri di build per vedere quale file impiega così tanto tempo.

Come esempio dei tipi di codice che possono causare problemi, questa sintesi di 38 righe richiede più di un minuto per essere compilata in beta7. Tutto questo è causato da questo blocco unico:

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

Semplifica questo con solo una linea o due e si compila quasi all'istante. Il problema è che qualcosa sta causando una crescita esponenziale (forse una crescita fattoriale) nel compilatore. Ovviamente non è l'ideale, e se riesci a isolare tali situazioni, dovresti aprire i radar per aiutare a risolvere questi problemi.


Non sono sicuro che tu abbia visto il mio commento sulla CompileSwiftfase. Prende tutti i file rapidi anche se solo uno è stato modificato. Quindi, se è un file che richiede del tempo (di cui dubito fortemente), il compilatore non ti dirà mai quale sia.
apouche,

10
Puoi compilare singoli file usando swiftcper vedere quanto tempo impiegano.
Rob Napier,

Mi scuso per non averti dato la generosità perché all'inizio non ci credo. Ho anche provato a compilare i file uno per uno, ma era complicato da fare (dovevo dare correttamente quadri e deps ogni volta), quindi ho rinunciato. Si prega di consultare la mia ultima risposta a questo post per una spiegazione completa
apouche

Non credo sia basato sulle dimensioni del progetto. Il mio progetto ha solo 4 file rapidi e improvvisamente ha iniziato a compilare incredibilmente lentamente. Si è acceso velocemente ieri. Non riesco a mettere il dito su qualcosa che ho fatto al mio progetto in particolare, tranne aggiungere icona e lanciare immagini.
Travis M.

33

Se stai cercando di identificare file specifici che rallentano il tempo di compilazione, potresti provare a compilarlo dalla tua riga di comando tramite xctool che ti darà tempi di compilazione file per file.

La cosa da notare è che, per impostazione predefinita, crea 2 file contemporaneamente per ogni core della CPU e non ti darà il tempo trascorso "netto", ma il tempo assoluto "utente". In questo modo tutti i tempi si uniformano tra file parallelizzati e sembrano molto simili.

Per ovviare a questo, impostare la -jobsbandiera su 1 , in modo da non parallelizzare le build dei file. Ci vorrà più tempo, ma alla fine avrai tempi di compilazione "netti" che puoi confrontare file per file.

Questo è un comando di esempio che dovrebbe fare il trucco:

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

L'output della fase "Compila file Swift" sarebbe simile a:

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

Da questo output è possibile identificare rapidamente quali file richiedono più tempo rispetto ad altri per la compilazione. Inoltre, puoi determinare con alta precisione se i tuoi refactoring (cast espliciti, suggerimenti sul tipo, ecc ...) stanno riducendo i tempi di compilazione per file specifici o meno.

NOTA: tecnicamente potresti anche farlo, xcodebuildma l'output è incredibilmente dettagliato e difficile da consumare.


1
Assicurati di avere l'ottimizzazione dell'intero modulo del progetto impostata su false, altrimenti non separerà i singoli file rapidi.
sab

1
Vedi Swift CompilerOptimization LevelperFast, Whole Module Optimization [-O -whole-module-optimization]
Matt

27

Nel mio caso, Xcode 7 non ha fatto alcuna differenza. Ho avuto più funzioni che richiedono diversi secondi per la compilazione.

Esempio

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

Dopo aver scartato gli optionals, il tempo di costruzione è sceso del 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)

Vedi altri esempi in questo post e in questo post .

Build Time Analyzer per Xcode

Ho sviluppato un plug-in Xcode che può tornare utile per chiunque abbia riscontrato questi problemi.

Immagine

Sembra che ci siano miglioramenti in arrivo in Swift 3, quindi speriamo di vedere il nostro codice Swift compilare più velocemente allora.


Fantastico, spero di poterti dare più di +1. sei vero e anche il tuo plugin è fantastico. l'ho usato e il mio tempo di compilazione sta diminuendo, il che significa uno sviluppo superveloce perché questi opzionali a volte sono un incubo e causano un rallentamento del compilatore.
hardikdevios,

Fantastico! Il tuo strumento mi aiuta molto. Grazie
Phil,

Ottimo plugin - Davvero utile! Grazie
365SplendidSuns

@Robert Gummesson, abbiamo qualche strumento per il codice Objective-C?
Ashok,

20

Probabilmente non possiamo correggere il compilatore Swift, ma qualcosa che possiamo correggere è il nostro codice!

C'è un'opzione nascosta a Swift compilatore che stampa gli intervalli di tempo esatti che compilatore prende per compilare ogni singola funzione: -Xfrontend -debug-time-function-bodies. Ci permette di trovare colli di bottiglia nel nostro codice e migliorare significativamente i tempi di compilazione.

Esegui semplicemente quanto segue nel terminale e analizza i risultati:

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

Il fantastico Brian Irace ha scritto un articolo brillante al riguardo Profilando i tempi di compilazione di Swift .


2
Per quelli con zsh alias grep='noglob grep'prima, altrimenti grep non funzionerà
Jaime Agudo

16

La soluzione è il casting.

Avevo una vasta gamma di tonnellate di dizionari, in questo modo:

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

Ci sono voluti circa 40 minuti per compilarlo. Fino a quando ho lanciato i dizionari in questo modo:

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

Questo ha funzionato per quasi tutti gli altri problemi che ho riscontrato per quanto riguarda i tipi di dati che ho codificato nella mia applicazione.


6
bene sì, fa parte delle ottimizzazioni che fai per migliorare i tempi di compilazione, ma il problema principale con l'attuale compilatore rapido è che ricompila ancora tutto il singolo file rapido ogni volta che apporti la minima modifica.
aprile

4
Sarebbe divertente se non fosse così triste.
Tom Andersen,

15

Una cosa da notare è che il motore di inferenza del tipo Swift può essere molto lento con i tipi nidificati. Puoi avere un'idea generale di ciò che sta causando la lentezza guardando il registro di build per le singole unità di compilazione che richiedono molto tempo e quindi copiando e incollando il comando completo generato da Xcode in una finestra Terminale e quindi premendo CTRL- \ per ottenere un po 'di diagnostica. Dai un'occhiata a http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times per un esempio completo.


Questa è per me la risposta migliore (vedi il link). Ho potuto facilmente trovare le due diverse linee che erano un problema e risolverlo decomprimendo le mie linee in linee più piccole.
Nico,

Questa è una risposta molto utile perché mostra come trovare dove il compilatore è impazzito. Nel mio caso è stato il seguente: 'curScore [curPlayer% 2] + curScore [2 + curPlayer% 2] == 3 && maker% 2 == curPlayer% 2' Non appena l'ho spostato da 'if' a 'let ", il risultato fu che" l'espressione era troppo complessa per essere risolta in tempi ragionevoli; si consideri di suddividere l'espressione in distinte sottoespressioni "
Dmitry,

Questo è sicuramente il modo più utile per risolvere questo problema.
Richard Venable,

9

Assicurati anche che durante la compilazione per il debug (Swift o Objective-C), imposti su Build Active Architecture Only:

inserisci qui la descrizione dell'immagine


6

Dato che tutto questo è in beta, e dato che il compilatore Swift non è (almeno ad oggi) aperto, suppongo che non ci sia una vera risposta alla tua domanda.

Prima di tutto, confrontare Objective-C con il compilatore Swift è in qualche modo crudele. Swift è ancora in versione beta e sono sicuro che Apple stia lavorando per fornire funzionalità e correggere bug, più che fornire la velocità della luce (non inizi a costruire una casa acquistando i mobili). Immagino che Apple ottimizzerà il compilatore a tempo debito.

Se per qualche motivo tutti i file di origine devono essere compilati completamente, un'opzione potrebbe essere quella di creare moduli / librerie separate. Ma questa opzione non è ancora possibile, poiché Swift non può consentire le librerie fino a quando la lingua non è stabile.

La mia ipotesi è che ottimizzeranno il compilatore. Per lo stesso motivo per cui non possiamo creare moduli precompilati, è possibile che il compilatore debba compilare tutto da zero. Ma una volta che la lingua raggiungerà una versione stabile e il formato dei binari non cambierà più, saremo in grado di creare le nostre librerie e forse (?) Il compilatore sarà anche in grado di ottimizzare il suo lavoro.

Solo indovinando, però, perché solo Apple sa ...


"Per lo stesso motivo per cui non è possibile creare moduli precompilati, è possibile che il compilatore debba compilare tutto da zero." bella osservazione, non ci avevo pensato prima.
Chakrit,

1
2017 e ancora lento
Pedro Paulo Amorim il

2017 con Xcode 9 e nuovo sistema di compilazione e ancora lento
pableiros,

2018 con Xcode 9, ho un progetto con oltre 50 file rapidi, se eseguo clean build, ora ha superato i 5 minuti e la mia compilation non è ancora terminata.
Chen Li Yong,

5

Per Xcode 8, vai alle impostazioni del progetto, quindi Editor> Aggiungi impostazione build> Aggiungi impostazione definita dall'utente e aggiungi quanto segue:

SWIFT_WHOLE_MODULE_OPTIMIZATION = YES

L'aggiunta di questo flag ha fatto cadere miracolosamente i nostri tempi di compilazione di clean-build da 7 minuti a 65 secondi per un progetto rapido 40KLOC. Inoltre può confermare che 2 amici hanno visto miglioramenti simili nei progetti aziendali.

Posso solo supporre che si tratti di una specie di bug in Xcode 8.0

EDIT: sembra che non funzioni più in Xcode 8.3 per alcune persone.


2
Dove sono le "impostazioni del progetto" per favore?
Raniys,

@Raniys Fai clic sull'icona blu a livello di radice nel riquadro sinistro in Xcode.
Chris,

Sto scoprendo che a partire da Xcode 8.3 (non beta) questo non funziona più nel mio caso :(
Chris

4

Sfortunatamente, il compilatore Swift non è ancora ottimizzato per una compilazione rapida e incrementale (a partire da Xcode 6.3 beta). Nel frattempo puoi utilizzare alcune delle seguenti tecniche per migliorare il tempo di compilazione di Swift:

  • Dividi l'app in Frameworks per ridurre l'impatto della ricompilazione. Ma tieni presente che devi evitare dipendenze cicliche nella tua app. Per ulteriori informazioni su questo argomento, consulta questo post: http://bits.citrusbyte.com/improving-swift-compile-time/

  • Usa Swift per parti del tuo progetto che sono abbastanza stabili e non cambiano spesso. Per altre aree in cui è necessario cambiare molto spesso o aree che richiedono molte iterazioni di compilazione / esecuzione per essere complete (quasi tutti gli elementi correlati all'interfaccia utente), utilizzare meglio Objective-C con un approccio mix-and-match.

  • Prova a inserire il codice di runtime con "Injection for Xcode"

  • Usa il metodo roopc: http://roopc.net/posts/2014/speeding-up-swift-builds/

  • Rilascia il rapido motore di inferenza del tipo dando alcuni suggerimenti con cast espliciti.


4

La costruzione di array e dizionari rapidi sembra essere una causa piuttosto popolare per questo (specialmente per te che provieni da un background di Ruby ), cioè,

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"]

sarà probabilmente la causa in cui questo dovrebbe risolverlo:

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

4

Per il debug e il test, assicurati di utilizzare le seguenti impostazioni per ridurre il tempo di compilazione da circa 20 minuti a meno di 2 minuti,

  1. Nelle impostazioni di compilazione del progetto, cerca "Ottimizzazione" Ruota Debug su "Più veloce [-O3]" o superiore.
  2. Imposta Build per Active Architecture: SÌ
  3. Formato informazioni di debug: DWARF
  4. Ottimizzazione dell'intero modulo: NO

Ho perso innumerevoli ore aspettando che il progetto venisse realizzato solo per rendermi conto che dovevo apportare quel piccolo cambiamento e ho dovuto aspettare altri 30 minuti per testarlo. Queste sono le impostazioni che hanno funzionato per me. (Sto ancora sperimentando le impostazioni)

Tuttavia, assicurati di impostare almeno "DWARF con dSYM" (se vuoi monitorare la tua applicazione) e Build Active Architecture su "NO" affinché Release / Archiviazione invii a iTunes Connect (ricordo di aver sprecato alcune ore anche qui).


4
Potrei sbagliarmi, ma impostare livelli di ottimizzazione aumentati non aumenterebbe effettivamente i tempi di costruzione? I livelli di ottimizzazione miglioreranno le prestazioni di runtime.
Michael Waterfall,

1
Set Build for Active Architecture: YESmi ha dato una riduzione del 45% circa nel tempo di compilazione. Grazie tante.
Jean Le Moignan,

4

Il compilatore impiega molto tempo a dedurre e verificare i tipi. Quindi l'aggiunta di annotazioni di tipo aiuta molto il compilatore.

Se hai molte chiamate a funzioni concatenate come

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

Quindi il compilatore impiega un po 'di tempo per capire quale sumdovrebbe essere il tipo di . L'aggiunta del tipo aiuta. Ciò che aiuta anche è tirare i passaggi intermittenti in variabili separate.

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: +)

Soprattutto per i tipi numerici CGFloat, Intpuò aiutare molto. Un numero letterale come 2può rappresentare molti tipi numerici diversi. Quindi il compilatore deve capire dal contesto quale sia.

+Dovrebbero anche essere evitate le funzioni che richiedono molto tempo per cercare . L'uso di più +per concatenare più array è lento perché il compilatore deve capire quale implementazione di +dovrebbe essere chiamata per ciascuno +. Quindi usa un var a: [Foo]con append()invece se possibile.

Puoi aggiungere un avviso per rilevare quali funzioni sono lente da compilare in Xcode .

In Impostazioni di costruzione per il tuo obiettivo cerca altre bandiere veloci e aggiungi

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

avvisare per ogni funzione che richiede più di 100 ms per la compilazione.


4

Per i progetti che mescolano C-Obiettivo e Swift codice, possiamo impostare -enable-bridging-pchin Other Swift Flags. In questo modo, l'intestazione ponte viene analizzata una sola volta e il risultato (un file "intestazione precompilata" o "PCH" temporaneo viene memorizzato nella cache e riutilizzato in tutti i file Swift nella destinazione. Apple ha affermato che riduce i tempi di costruzione del 30%. Link di riferimento:

NOTA: funziona solo per Swift 3.1 e versioni successive.


2

Il riavvio del mio Mac ha fatto miracoli per questo problema. Sono passato da build da 15 minuti a build da 30 secondi semplicemente riavviando.


1

Il rapido tempo di compilazione è stato migliorato nel nuovo Xcode 6.3

Miglioramenti del compilatore

Il compilatore Swift 1.2 è stato progettato per essere più stabile e migliorare le prestazioni in ogni modo. Queste modifiche offrono anche un'esperienza migliore quando si lavora con Swift in Xcode. Alcuni dei miglioramenti più visibili includono:

Build incrementali

I file di origine che non sono stati modificati non verranno più ricompilati per impostazione predefinita, il che migliorerà in modo significativo i tempi di compilazione per i casi più comuni. Modifiche strutturali più grandi al codice potrebbero richiedere la ricostruzione di più file.

Eseguibili più veloci

Le build di debug producono file binari che funzionano molto più velocemente e nuove ottimizzazioni offrono prestazioni di build di rilascio ancora migliori.

Migliore diagnostica del compilatore

Messaggi di errore e di avviso più chiari, insieme al nuovo Fix-it, facilitano la scrittura del codice Swift 1.2 corretto.

Miglioramenti della stabilità

Gli arresti anomali del compilatore più comuni sono stati corretti. Dovresti anche vedere meno avvisi di SourceKit nell'editor Xcode.


0

Ecco un altro caso che può causare enormi rallentamenti con l'inferenza del tipo. Operatori di coalescenza .

Linee che cambiano come:

abs(some_optional_variable ?? 0)

per

abs((some_optional_variable ?? 0) as VARIABLE_TYPE)

mi ha aiutato a portare il mio tempo di compilazione dagli anni '70 ai 13 '


0

Nulla ha funzionato per me in Xcode 6.3.1 - quando ho aggiunto circa 100 file Swift, Xcode è stato impiccato casualmente su build e / o indicizzazione. Ho provato un'opzione modulare senza successo.

L'installazione e l'utilizzo di Xcode 6.4 Beta ha funzionato davvero per me.


0

Per me ha funzionato come per magia: Speed ​​Up Swift Compilation . Ha ridotto i tempi di compilazione a 3 minuti da 10 minuti.

Si dice che si dovrebbe accendere il Whole Module Optimization, mentre l'aggiunta -Ononedi Other Swift Flags.

Sto usando Swift 3il Xcode 8.3/Xcode 8.2 .


0

La miscelazione di valori letterali interi e letterali float in un'unica espressione provoca anche lunghi tempi di compilazione.

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

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

Molte espressioni in fase di compilazione di 1000 + ms vengono ridotte a 10 ~ 100 ms dopo aver inserito un .0valore letterale after after integer.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.