¿Por qué el tiempo de compilación Swift es tan lento?

210

Estoy usando Xcode 6 Beta 6.

Esto es algo que me ha estado molestando desde hace un tiempo, pero está llegando a un punto en el que ahora apenas se puede usar.

Mi proyecto está empezando a tener una buena tamaño de 65 archivos Swift y algunos archivos Objective-C en puente (que en realidad no son la causa del problema).

Parece que cualquier ligera modificación en cualquier archivo Swift (como agregar un espacio en blanco simple en una clase que apenas se usa en la aplicación) hará que se vuelvan a compilar todos los archivos Swift para el objetivo especificado.

Después de una investigación más profunda, descubrí que lo que toma casi el 100% del tiempo del compilador es la CompileSwiftfase en la que Xcode ejecuta elswiftc comando en todos los archivos Swift de su objetivo.

Investigué un poco más, y si solo mantengo al delegado de la aplicación con un controlador predeterminado, la compilación es muy rápida, pero a medida que agregaba más y más archivos de mi proyecto, el tiempo de compilación comenzaba a ser muy lento.

Ahora con solo 65 archivos de origen, se tarda unos 8/10 segundos en compilar cada vez. No muy rápido en absoluto.

No he visto ninguna publicación que hable sobre este problema, excepto esta , pero era una versión antigua de Xcode 6. Así que me pregunto si soy el único en ese caso.

ACTUALIZAR

He comprobado algunos proyectos Swift en GitHub como Alamofire , Euler y CryptoSwift , pero ninguno de ellos tenía suficientes archivos Swift para comparar. El único proyecto que encontré que estaba comenzando a tener un tamaño decente fue SwiftHN , y aunque solo tenía una docena de archivos fuente, todavía pude verificar lo mismo, un espacio simple y todo el proyecto necesitaba una recompilación que comenzaba a tomar un poco tiempo (2/3 segundos).

En comparación con el código Objective-C, donde tanto el analizador como la compilación son extremadamente rápidos, realmente parece que Swift nunca podrá manejar grandes proyectos, pero por favor dígame que estoy equivocado.

ACTUALIZAR con Xcode 6 Beta 7

Todavía no hay mejora alguna. Esto está empezando a ponerse ridículo. Con la falta de #importSwift, realmente no veo cómo Apple podrá optimizar esto.

ACTUALIZACIÓN con Xcode 6.3 y Swift 1.2

Apple ha agregado compilaciones incrementales (y muchas otras optimizaciones del compilador). Tienes que migrar tu código a Swift 1.2 para ver esos beneficios, pero Apple agregó una herramienta en Xcode 6.3 para ayudarte a hacerlo:

Ingrese la descripción de la imagen aquí

SIN EMBARGO

No te regocijes demasiado rápido como lo hice. El solucionador de gráficos que usan para hacer que la construcción sea incremental aún no está muy bien optimizado.

De hecho, en primer lugar, no analiza los cambios en la firma de la función, por lo que si agrega un espacio en el bloque de un método, se volverán a compilar todos los archivos dependiendo de esa clase.

En segundo lugar, parece crear el árbol en función de los archivos que se volvieron a compilar, incluso si un cambio no los afecta. Por ejemplo, si mueve estas tres clases a archivos diferentes

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

Ahora, si modifica FileA, el compilador obviamente marcará FileAcomo recompilado. También se recompilará FileB(eso estaría bien en función de los cambios FileA), pero también FileCporque FileBse vuelve a compilar, y eso es bastante malo porque FileCnunca se usa FileAaquí.

Así que espero que mejoren el solucionador de árboles de dependencia ... Abrí un radar con este código de muestra.

ACTUALIZACIÓN Con Xcode 7 beta 5 y Swift 2.0

Ayer Apple lanzó la versión beta 5 y dentro de las notas de la versión pudimos ver:

Swift Language & Compiler • Compilaciones incrementales: cambiar solo el cuerpo de una función ya no debería causar la reconstrucción de archivos dependientes. (15352929)

Lo he probado y debo decir que está funcionando realmente (¡realmente!) Ahora. Optimizaron enormemente las compilaciones incrementales en Swift.

Le recomiendo que cree una swift2.0rama y mantenga su código actualizado con XCode 7 beta 5. Le agradarán las mejoras del compilador (sin embargo, diría que el estado global de XCode 7 sigue siendo lento y con errores)

ACTUALIZAR con Xcode 8.2

Ha pasado un tiempo desde mi última actualización sobre este tema, así que aquí está.

Nuestra aplicación ahora tiene aproximadamente 20k líneas de código Swift casi exclusivamente, que es decente pero no sobresaliente. Sufrió una migración rápida 2 y rápida 3. Se tarda unos 5 / 6m en compilar en una Macbook pro de mediados de 2014 (Intel Core i7 de 2.5 GHz), lo cual está bien en una compilación limpia.

Sin embargo, la construcción incremental sigue siendo una broma a pesar de que Apple afirma que:

Xcode no reconstruirá un objetivo completo cuando solo se hayan producido pequeños cambios. (28892475)

Obviamente, creo que muchos de nosotros simplemente nos reímos después de revisar estas tonterías (agregar una propiedad privada (¡privada!) A cualquier archivo de mi proyecto recompilará todo ...)

Me gustaría señalarles este hilo en los foros de desarrolladores de Apple que tiene más información sobre el problema (así como también agradeció la comunicación de desarrollo de Apple sobre el tema de vez en cuando)

Básicamente, las personas han ideado algunas cosas para tratar de mejorar la compilación incremental:

  1. Agregar una HEADER_MAP_USES_VFSconfiguración de proyecto establecida entrue
  2. Deshabilitar Find implicit dependenciesde su esquema
  3. Cree un nuevo proyecto y mueva su jerarquía de archivos al nuevo.

Intentaré la solución 3 pero la solución 1/2 no funcionó para nosotros.

Lo que es irónicamente gracioso en toda esta situación es que al mirar la primera publicación sobre este tema, estábamos usando Xcode 6 con el código Swift 1 o Swift 1.1 cuando llegamos a la primera lentitud de compilaciones y ahora unos dos años más tarde a pesar de las mejoras reales de Apple. la situación es tan mala como lo fue con Xcode 6. Qué irónico.

En realidad REALMENTE lamento elegido Swift sobre Obj / C para nuestro proyecto debido a la frustración diaria que esto implica. (Incluso cambio a AppCode pero esa es otra historia)

De todos modos, veo que esta publicación SO tiene más de 32k vistas y 143 ups al momento de escribir esto, así que supongo que no soy el único. Esperen, muchachos, a pesar de ser pesimistas sobre esta situación, puede haber algo de luz al final del túnel.

Si tienes tiempo (¡y coraje!), Supongo que Apple agradece el radar sobre esto.

¡Hasta la próxima! Salud

ACTUALIZAR con Xcode 9

Tropezar con esto hoy. Xcode presentó silenciosamente un nuevo sistema de compilación para mejorar el horrible rendimiento actual. Debe habilitarlo a través de la configuración del espacio de trabajo.

ingrese la descripción de la imagen aquí

Ya lo probé, pero actualizaré esta publicación una vez que haya terminado. Sin embargo, parece prometedor.

apouche
fuente
1
¡Interesante! Me pregunto si es solo una optimización que falta o la necesidad de analizar tantos archivos ya que no hay archivos de interfaz.
zaph
2
Tuve problemas similares, y al final me di cuenta de que era debido a los operadores personalizados utilizados en las clases de entidad para deserializarse de JSON. Si está utilizando alguno, le sugiero que intente convertir a la función normal uno por uno y ver si algo cambia.
Antonio
44
La compilación se ha vuelto extremadamente lenta en mi proyecto desde XCode 6 beta 6. Donde no estoy seguro si se debe a cambios en la beta o debido a mi código. Pero mi proyecto aún no es grande (~ 40-50 archivos Swift).
BadmintonCat
2
La compilación se ha vuelto insoportablemente lenta a medida que mi proyecto ha crecido. También dependo de varias cápsulas, lo que estoy seguro exaspera el problema. Esto está utilizando la versión reciente no beta.
Andy
2
La compilación incremental todavía se realiza en un "análisis de dependencia conservador, por lo que aún puede ver más reconstrucción de archivos de la absolutamente necesaria". Con suerte, mejorará con el tiempo.
nmdias

Respuestas:

70

Bueno, resultó que Rob Napier tenía razón. Fue un solo archivo (en realidad, un método) lo que causó que el compilador se volviera loco.

Ahora no me malinterpretes. Swift recompila todos sus archivos cada vez, pero lo mejor ahora es que Apple agregó comentarios de compilación en tiempo real sobre los archivos que compila, por lo que Xcode 6 GM ahora muestra qué archivos Swift se están compilando y el estado de la compilación en tiempo real como puedes ver en esta captura de pantalla:

Ingrese la descripción de la imagen aquí

Esto es muy útil para saber cuál de sus archivos está tardando tanto. En mi caso fue este código:

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

return dic.copy() as NSDictionary

porque la propiedad titleera de tipo var title:String?y no NSString. El compilador se estaba volviendo loco al agregarlo al NSMutableDictionary.

Cambiándolo a:

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

return dic.copy() as NSDictionary

hizo que la compilación pasara de 10/15 segundos (tal vez incluso más) a un solo segundo ... increíble.

apouche
fuente
3
Gracias por seguir con la respuesta. Esto puede ser muy útil para otros que persiguen allí el motor de inferencia de tipos se atasca durante la compilación.
Rob Napier
1
¿Dónde llegaste a esta vista @apouche? No lo veo en xcode
Eric
2
Debe
1
Sí, estoy seguro de que Apple optimizará esto más adelante, de lo contrario, hacer proyectos en el mundo real con rapidez está condenado aquí y allá.
apouche
1
¿Cómo puedo acceder a esta herramienta que muestra qué archivos se están compilando?
jgvb
42

Hemos intentado algunas cosas para combatir esto, ya que tenemos alrededor de 100k líneas de código Swift y 300k líneas de código ObjC.

Nuestro primer paso fue optimizar todas las funciones de acuerdo con la salida de los tiempos de compilación de funciones (por ejemplo, como se describe aquí https://thatthinginswift.com/debug-long-compile-times-swift/ )

A continuación, escribimos un script para fusionar todos los archivos rápidos en un solo archivo, esto rompe los niveles de acceso, pero llevó nuestro tiempo de compilación de 5-6 minutos a ~ 1 minuto.

Esto ya no está vigente porque le preguntamos a Apple sobre esto y nos aconsejaron que deberíamos hacer lo siguiente:

  1. Active 'optimización de módulo completo' en la configuración de compilación 'Compilador rápido - Generación de código'. Seleccione'Fast, Whole Module Optimization'

ingrese la descripción de la imagen aquí

  1. En 'Swift Compiler - Custom Flags', para sus compilaciones de desarrollo, agregue '-Onone'

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Cuando se establecen estos indicadores, el compilador compilará todos los archivos Swift en un solo paso. Descubrimos que con nuestro script de fusión esto es mucho más rápido que compilar archivos individualmente. Sin embargo, sin la ' -Onone'anulación ' , también optimizará todo el módulo, que es más lento. Cuando configuramos la '-Onone'bandera en las otras banderas Swift, detiene la optimización, pero no deja de compilar todos los archivos Swift en un solo paso.

Para obtener más información sobre la optimización de todo el módulo, consulte la publicación del blog de Apple aquí: https://swift.org/blog/whole-module-optimizations/

Hemos encontrado que estas configuraciones permiten que nuestro código Swift se compile en 30 segundos :-) No tengo evidencia de cómo funcionaría en otros proyectos, pero sugiero probarlo si los tiempos de compilación Swift siguen siendo un problema para usted.

Tenga en cuenta que para las compilaciones de su tienda de aplicaciones, debe '-Onone'omitir el indicador, ya que se recomienda la optimización para las compilaciones de producción.

Sam Stow
fuente
44
Muchas gracias por este consejo! Simplemente no entiendo por qué no hay nada de eso en las fuentes oficiales (al menos fácil de encontrar), por ejemplo, el artículo que menciona debe (¡debe!) Tener el comentario al respecto -Onone. No podemos utilizar la optimización completa del módulo por ahora porque hace que el compilador se bloquee ... Pero su consejo aumenta casi x10 la velocidad de construcción. En MacBook Air (anual 2013) se estaba construyendo alrededor de 8 minutos, ahora se reduce a alrededor de 1 minuto y la mitad de ese tiempo se pasa cambiando entre objetivos (tenemos aplicaciones, extensiones y pocos marcos internos) y compilando guiones gráficos
Ilya Puchka
También probé este método y es el único método mencionado que incluye -Onone y disminuye significativamente el tiempo de construcción.
Vlad
Trabaja con el mío también. Usando -Ononeayuda para reducir los tiempos de construcción. Muchas gracias amigo!
nahung89
34

Es probable que tenga poco que ver con el tamaño de su proyecto. Probablemente sea un código específico, posiblemente incluso una sola línea. Puede probar esto intentando compilar un archivo a la vez en lugar de todo el proyecto. O intente ver los registros de compilación para ver qué archivo está tardando tanto.

Como ejemplo de los tipos de código que pueden causar problemas, esta esencia de 38 líneas tarda más de un minuto en compilarse en beta7. Todo esto es causado por este bloque:

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

Simplifique eso con solo una línea o dos y se compila casi al instante. El problema es que esto está causando un crecimiento exponencial (posiblemente un crecimiento factorial) en el compilador. Obviamente, eso no es lo ideal, y si puede aislar tales situaciones, debe abrir los radares para ayudar a solucionar esos problemas.

Rob Napier
fuente
No estoy seguro de que haya visto mi comentario sobre la CompileSwiftfase. Toma todos los archivos rápidos incluso si solo se modificó uno. Entonces, si se trata de un archivo que está tardando un tiempo (lo cual dudo mucho), el compilador nunca le dirá cuál es.
apouche
10
Puede compilar archivos individuales usando swiftcpara ver cuánto tardan.
Rob Napier
Pido disculpas por no darte la recompensa porque no lo creo al principio. También traté de compilar archivos uno por uno, pero fue muy engorroso (tenía que dar marcos y deps correctamente cada vez), así que me di por vencido. Por favor, vea mi última respuesta a esta entrada para la explicación completa
apouche
No creo que se base en el tamaño del proyecto. Mi proyecto solo tiene 4 archivos rápidos y de repente comenzó a compilarse increíblemente lento. Estaba iluminando rápido ayer. No puedo señalar nada de lo que hice a mi proyecto en particular, excepto agregar ícono e iniciar imágenes.
Travis M.
33

Si está tratando de identificar archivos específicos que ralentizan su tiempo de compilación, puede intentar compilarlo desde su línea de comandos a través de xctool, que le dará tiempos de compilación archivo por archivo.

Lo que hay que tener en cuenta es que, de forma predeterminada, crea 2 archivos simultáneamente por cada núcleo de CPU, y no le dará el tiempo transcurrido "neto", sino el tiempo absoluto de "usuario". De esta manera, todos los tiempos se igualan entre archivos paralelos y se ven muy similares.

Para superar esto, establezca el -jobsindicador en 1 , de modo que no paralelice las compilaciones de archivos. Tomará más tiempo, pero al final tendrá tiempos de compilación "netos" que puede comparar archivo por archivo.

Este es un comando de ejemplo que debería hacer el truco:

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

El resultado de la fase "Compilar archivos Swift" sería algo así como:

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

A partir de esta salida, puede identificar rápidamente qué archivos tardan más que otros en compilarse. Además, puede determinar con alta precisión si sus refactorizaciones (conversiones explícitas, sugerencias de tipo, etc.) están reduciendo los tiempos de compilación para archivos específicos o no.

NOTA: técnicamente también podría hacerlo, xcodebuildpero el resultado es increíblemente detallado y difícil de consumir.

Andrea Sprega
fuente
1
Solo asegúrese de tener la optimización de todo el módulo de su proyecto establecida en falso, o no separará los archivos rápidos individuales.
sabes
1
Ver Swift CompilerOptimization LevelparaFast, Whole Module Optimization [-O -whole-module-optimization]
Matt
27

En mi caso, Xcode 7 no hizo ninguna diferencia. Tenía varias funciones que requieren varios segundos para compilar.

Ejemplo

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

Después de desenvolver las opciones, el tiempo de construcción cayó en un 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)

Ver más ejemplos en esta publicación y esta publicación .

Build Time Analyzer para Xcode

Yo desarrollé un plug-in de Xcode que puede ser útil para cualquier persona que experimenta estos problemas.

imagen

Parece que hay mejoras en Swift 3, así que esperamos ver nuestro código Swift compilar más rápido.

Robert Gummesson
fuente
Impresionante, espero poder darte más de +1. eres verdadero y tu complemento también es genial. Lo he usado y mi tiempo de compilación se está cayendo, lo que significa un desarrollo súper rápido porque estas opciones son pesadilla a veces y hacen que el compilador se ralentice.
hardikdevios
Fantastico! Tu herramienta me ayuda mucho. Gracias
Phil
Gran complemento: ¡realmente útil! Gracias
365SplendidSuns
@Robert Gummesson, ¿tenemos alguna herramienta para el Código Objective-C?
Ashok
20

Probablemente no podamos arreglar el compilador Swift, ¡pero algo que podemos arreglar es nuestro código!

Hay una opción oculta en el compilador Swift que imprime los intervalos de tiempo exactos que toma el compilador para compilar cada función: -Xfrontend -debug-time-function-bodies . Nos permite encontrar cuellos de botella en nuestro código y mejorar significativamente el tiempo de compilación.

Simplemente ejecute lo siguiente en la terminal y analice los resultados:

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

Impresionante Brian Irace escribió un artículo brillante al respecto Perfilando tus tiempos de compilación Swift .

Valentin Shergin
fuente
2
Para aquellos con zsh alias grep='noglob grep'primero, de lo contrario grep no funcionará
Jaime Agudo
16

La solución es el casting.

Tenía una gran variedad de toneladas de diccionarios, como este:

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

Le tomó aproximadamente 40 minutos compilarlo. Hasta que lancé los diccionarios así:

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

Esto funcionó para casi cualquier otro problema que encontré con respecto a los tipos de datos que codifiqué en mi aplicación.

YichenBman
fuente
66
bueno, sí, es parte de las optimizaciones que haces para mejorar los tiempos de compilación, pero aún así el principal problema con el compilador swift actual, es que aún recompila todo el archivo swift cada vez que haces la más mínima modificación.
apouche
44
Eso sería divertido si no fuera tan triste.
Tom Andersen
15

Una cosa a tener en cuenta es que el motor de inferencia de tipo Swift puede ser muy lento con tipos anidados. Puede obtener una idea general sobre lo que está causando la lentitud mirando el registro de compilación de unidades de compilación individuales que están tardando mucho tiempo y luego copiando y pegando el comando completo generado por Xcode en una ventana de Terminal y luego presionando CTRL- \ para obtener Algunos diagnósticos. Eche un vistazo a http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times para ver un ejemplo completo.

marcprux
fuente
Esa es para mí la mejor respuesta (ver el enlace). PODÍA encontrar FÁCILMENTE las dos líneas diferentes que eran un problema y lo resolví descomponiendo mis líneas en líneas más pequeñas.
Nico
Esa es una respuesta muy útil porque muestra cómo encontrar dónde se volvió loco el compilador. En mi caso, fue lo siguiente: 'curScore [curPlayer% 2] + curScore [2 + curPlayer% 2] == 3 && maker% 2 == curPlayer% 2' Tan pronto como lo moví de 'if' a 'let ', resultó en "la expresión era demasiado compleja para ser resuelta en un tiempo razonable; considere dividir la expresión en sub-expresiones distintas"
Dmitry
Esta es definitivamente la forma más útil de resolver este problema.
Richard Venable
9

También asegúrese de que al compilar para la depuración (ya sea Swift u Objective-C), configure solo Build Active Architecture:

ingrese la descripción de la imagen aquí

Rivera
fuente
6

Dado que todo esto está en Beta, y dado que el compilador Swift (al menos a partir de hoy) no está abierto, supongo que no hay una respuesta real a su pregunta.

En primer lugar, comparar Objective-C con el compilador Swift es de alguna manera cruel. Swift todavía está en Beta, y estoy seguro de que Apple está trabajando para proporcionar funcionalidad y corregir errores, más que proporcionar la velocidad del rayo (no comienzas a construir una casa comprando los muebles). Supongo que Apple optimizará el compilador a su debido tiempo.

Si por alguna razón todos los archivos fuente tienen que compilarse por completo, una opción podría ser crear módulos / bibliotecas separados. Pero esta opción aún no es posible, ya que Swift no puede permitir bibliotecas hasta que el idioma sea estable.

Supongo que optimizarán el compilador. Por la misma razón por la que no podemos crear módulos precompilados, bien podría ser que el compilador necesite compilar todo desde cero. Pero una vez que el idioma alcanza una versión estable y el formato de los binarios ya no cambia, podremos crear nuestras bibliotecas, y tal vez (?) El compilador también podrá optimizar su trabajo.

Sin embargo, solo adivino, porque solo Apple sabe ...

Jorge
fuente
"Por la misma razón por la que no podemos crear módulos precompilados, bien podría ser que el compilador necesite compilar todo desde cero". buena observación, no lo había pensado de esa manera antes.
chakrit
1
2017 y todavía es lento
Pedro Paulo Amorim
2017 con Xcode 9 y nuevo sistema de construcción y aún lento
pableiros
2018 con Xcode 9, tengo un proyecto con más de 50 archivos rápidos, si hago una compilación limpia, ahora ha pasado 5 minutos y mi compilación aún no ha terminado.
Chen Li Yong
5

Para Xcode 8, vaya a la configuración del proyecto, luego Editor> Agregar configuración de compilación> Agregar configuración definida por el usuario y agregue lo siguiente:

SWIFT_WHOLE_MODULE_OPTIMIZATION = YES

Agregar esta bandera redujo nuestros tiempos de compilación de compilación limpia de 7 minutos a 65 segundos para un proyecto rápido de 40KLOC, milagrosamente. También puede confirmar que 2 amigos han visto mejoras similares en proyectos empresariales.

Solo puedo suponer que se trata de algún tipo de error en Xcode 8.0

EDITAR: Parece que ya no funciona en Xcode 8.3 para algunas personas.

Chris
fuente
2
¿Dónde está la "configuración del proyecto" por favor?
Raniys
@Raniys Haga clic en el icono azul en el nivel raíz en el panel izquierdo en Xcode.
Chris
Estoy descubriendo que a partir de Xcode 8.3 (no beta) esto ya no funciona en mi caso :(
Chris
4

Desafortunadamente, el compilador Swift aún no está optimizado para una compilación rápida e incremental (a partir de Xcode 6.3 beta). Mientras tanto, puede usar algunas de las siguientes técnicas para mejorar el tiempo de compilación de Swift:

  • Divida la aplicación en Frameworks para reducir el impacto de la recompilación. Pero tenga en cuenta que debe evitar las dependencias cíclicas en su aplicación. Para obtener más información sobre este tema, consulte esta publicación: http://bits.citrusbyte.com/improving-swift-compile-time/

  • Use Swift para partes de su proyecto que sean bastante estables y que no cambien con frecuencia. Para otras áreas en las que necesita cambiar muy a menudo o áreas que requieren muchas iteraciones de compilación / ejecución para completarse (casi cualquier cosa relacionada con la interfaz de usuario), use mejor Objective-C con un enfoque de combinación y combinación.

  • Pruebe la inyección de código de tiempo de ejecución con 'Injection for Xcode'

  • Utilice el método roopc: http://roopc.net/posts/2014/speeding-up-swift-builds/

  • Alivie el motor de inferencia de tipo rápido dando algunas pistas con lanzamientos explícitos.

vorterixe
fuente
4

La construcción rápida de matrices y diccionarios parece ser una causa bastante popular para esto (especialmente para ustedes que provienen de un fondo Ruby ), es decir,

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

probablemente será la causa donde esto debería solucionarlo:

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

Para depurar y probar, asegúrese de utilizar la siguiente configuración para reducir el tiempo de compilación de alrededor de 20 minutos a menos de 2 minutos,

  1. En la configuración de compilación del proyecto, busque "Optimización" Cambie la depuración a "Más rápido [-O3]" o superior.
  2. Establecer compilación para arquitectura activa: SÍ
  3. Formato de información de depuración: DWARF
  4. Optimización completa del módulo: NO

Perdí incontables horas esperando que el proyecto se construyera solo para darme cuenta de que tenía que hacer ese pequeño cambio y tuve que esperar otros 30 minutos para probarlo. Estas son las configuraciones que funcionaron para mí. (Todavía estoy experimentando con la configuración)

Pero asegúrese de al menos configurar "DWARF with dSYM" (si desea monitorear su aplicación) y Build Active Architecture en "NO" para Release / Archiving para enviar a iTunes Connect (recuerdo haber perdido algunas horas aquí también).

Mahesh
fuente
44
Puedo estar equivocado, pero ¿no establecer niveles de optimización aumentados en realidad aumentaría el tiempo de construcción? Los niveles de optimización mejorarán el rendimiento en tiempo de ejecución.
Michael Waterfall
1
Set Build for Active Architecture: YESme dio una reducción aproximada del 45% en el tiempo de compilación. Muchas gracias.
Jean Le Moignan
4

El compilador pasa mucho tiempo inferiendo y verificando los tipos. Por lo tanto, agregar anotaciones de tipo ayuda mucho al compilador.

Si tiene muchas llamadas a funciones encadenadas como

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

Luego, el compilador tarda un tiempo en averiguar cuál sumdebería ser el tipo de . Agregar el tipo ayuda. Lo que también ayuda es llevar los pasos intermitentes a variables separadas.

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

Especialmente para los tipos numéricos CGFloat, Intpuede ayudar mucho. Un número literal como2 puede representar muchos tipos numéricos diferentes. Por lo tanto, el compilador debe determinar, a partir del contexto, cuál es.

+También se deben evitar las funciones que requieren mucho tiempo para buscar . El uso de varios +para concatenar varios arreglos es lento porque el compilador necesita averiguar qué implementación de +debe llamarse para cada uno +. Entonces usa un var a: [Foo]conappend() en su lugar si es posible.

Puede agregar una advertencia para detectar qué funciones son lentas para compilar en Xcode .

En Configuración de compilación para su objetivo, busque Otras banderas rápidas y agregue

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

para advertir sobre cada función que tarda más de 100 ms en compilarse.

orkoden
fuente
4

Para los proyectos que mezclan Objetivo-C de código y Swift, podemos establecer -enable-bridging-pchen Other Swift Flags. Con esto, el encabezado de puente se analiza solo una vez, y el resultado (un "encabezado precompilado" o archivo "PCH" temporal) se almacena en caché y se reutiliza en todos los archivos Swift en el destino. Apple afirmó que disminuye el tiempo de construcción en un 30%. Link de referencia:

NOTA: Esto funciona solo para Swift 3.1 y superior.

iHS
fuente
2

Reiniciar mi Mac hizo maravillas con este problema. Pasé de 15 minutos a 30 segundos simplemente reiniciando.

Sigma4Life
fuente
1

Se mejoró el tiempo de compilación rápido en el nuevo Xcode 6.3

Mejoras del compilador

El compilador Swift 1.2 fue diseñado para ser más estable y mejorar el rendimiento en todos los sentidos. Estos cambios también proporcionan una mejor experiencia al trabajar con Swift en Xcode. Algunas de las mejoras más visibles incluyen:

Construcciones incrementales

Los archivos de origen que no han cambiado ya no se volverán a compilar de forma predeterminada, lo que mejorará significativamente los tiempos de compilación para la mayoría de los casos comunes. Los cambios estructurales más grandes en su código aún pueden requerir la reconstrucción de varios archivos.

Ejecutables más rápidos

Las compilaciones de depuración producen binarios que se ejecutan considerablemente más rápido, y las nuevas optimizaciones ofrecen un rendimiento de compilación de lanzamiento aún mejor.

Mejores diagnósticos del compilador

Los mensajes de error y advertencia más claros, junto con los nuevos Fix-its, facilitan la escritura del código Swift 1.2 adecuado.

Mejoras de estabilidad

Se han solucionado los bloqueos más comunes del compilador. También debería ver menos advertencias de SourceKit dentro del editor Xcode.

Vojtech Vrbka
fuente
0

Aquí hay otro caso que puede causar ralentizaciones masivas con inferencia de tipos. Operadores coalescentes .

Líneas cambiantes como:

abs(some_optional_variable ?? 0)

a

abs((some_optional_variable ?? 0) as VARIABLE_TYPE)

ayudó a llevar mi tiempo de compilación de los 70 a los 13

Harry mexicano
fuente
0

Nada funcionó para mí en Xcode 6.3.1: cuando agregué alrededor de 100 archivos Swift, Xcode colgó al azar en la compilación y / o indexación. He probado una opción modular sin éxito.

Instalar y usar Xcode 6.4 Beta realmente funcionó para mí.

hris.to
fuente
0

Esto ha funcionado como magia para mí: Speed ​​Up Swift Compilation . Redujo el tiempo de compilación a 3 minutos de 10 minutos.

Se dice que se debe encender el Whole Module Optimizationtiempo que añade -Ononeen Other Swift Flags.

Estoy usando Swift 3en Xcode 8.3/Xcode 8.2 .

Fragua
fuente
0

Mezclar el entero entero y el literal flotante en una expresión también causa un tiempo de compilación prolongado.

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

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

Muchas expresiones de tiempo de compilación de más de 1000 ms se reducen a 10 ~ 100 ms después de poner un .0literal entero después.

Chen OT
fuente