Estou usando o Xcode 6 Beta 6.
Isso é algo que me incomoda há algum tempo agora, mas está chegando a um ponto em que dificilmente pode ser usado agora.
Meu projeto está começando a ter um tamanho decente de 65 arquivos Swift e alguns arquivos Objective-C em ponte (que realmente não são a causa do problema).
Parece que qualquer pequena modificação em qualquer arquivo Swift (como adicionar um espaço em branco simples em uma classe que mal é usada no aplicativo) fará com que todos os arquivos Swift do destino especificado sejam recompilados.
Após uma investigação mais profunda, descobri que o que está consumindo praticamente 100% do tempo do compilador é a CompileSwift
fase em que o Xcode executa o swiftc
comando em todos os arquivos Swift do seu destino.
Eu fiz algumas investigações adicionais e, se eu mantiver o aplicativo delegado apenas com um controlador padrão, a compilação é muito rápida, mas como eu estava adicionando mais e mais dos meus arquivos de projeto, o tempo de compilação estava começando a ficar muito lento.
Agora, com apenas 65 arquivos de origem, leva cerca de 8/10 segundos para compilar a cada vez. Não é muito rápido .
Eu não vi nenhum post falando sobre esse problema, exceto este , mas era uma versão antiga do Xcode 6. Então, estou me perguntando se sou o único nesse caso.
ATUALIZAR
Eu verifiquei alguns projetos Swift no GitHub como Alamofire , Euler e CryptoSwift , mas nenhum deles tinha arquivos Swift suficientes para comparar. O único projeto que achei que estava começando um tamanho decente foi o SwiftHN e, embora tivesse apenas uma dúzia de arquivos de origem, ainda era possível verificar a mesma coisa, um espaço simples e todo o projeto precisavam de recompilação, que estava começando a demorar um pouco. pouco tempo (2/3 segundos).
Comparado com o código Objective-C, onde o analisador e a compilação são rápidos, parece que o Swift nunca será capaz de lidar com grandes projetos, mas, por favor, me diga que estou errado.
ATUALIZAÇÃO Com o Xcode 6 Beta 7
Ainda não houve nenhuma melhoria. Isso está começando a ficar ridículo. Com a falta de #import
Swift, eu realmente não vejo como a Apple poderá otimizar isso.
ATUALIZAÇÃO Com o Xcode 6.3 e o Swift 1.2
A Apple adicionou compilações incrementais (e muitas outras otimizações do compilador). Você precisa migrar seu código para o Swift 1.2 para ver esses benefícios, mas a Apple adicionou uma ferramenta no Xcode 6.3 para ajudá-lo:
CONTUDO
Não se alegrem muito rápido como eu. O solucionador de gráficos que eles usam para tornar a construção incremental ainda não está muito otimizado.
De fato, primeiro, ele não considera as alterações de assinatura de função; portanto, se você adicionar um espaço no bloco de um método, todos os arquivos, dependendo dessa classe, serão recompilados.
Segundo, parece criar a árvore com base nos arquivos que foram recompilados, mesmo que uma alteração não os afete. Por exemplo, se você mover essas três classes para arquivos diferentes
class FileA: NSObject {
var foo:String?
}
class FileB: NSObject {
var bar:FileA?
}
class FileC: NSObject {
var baz:FileB?
}
Agora, se você modificar FileA
, o compilador obviamente marcará FileA
como recompilado. Também recompilará FileB
(isso seria bom com base nas alterações de FileA
), mas também FileC
porque FileB
é recompilado, e isso é muito ruim porque FileC
nunca é usado FileA
aqui.
Espero que eles melhorem o solucionador de árvores de dependência ... Abri um radar com esse código de exemplo.
ATUALIZAÇÃO Com Xcode 7 beta 5 e Swift 2.0
Ontem a Apple lançou o beta 5 e dentro das notas de lançamento pudemos ver:
Swift Language & Compiler • Compilações incrementais: alterar apenas o corpo de uma função não deve mais fazer com que os arquivos dependentes sejam reconstruídos. (15352929)
Eu tentei e devo dizer que está funcionando muito (realmente!) Bem agora. Eles otimizaram muito as construções incrementais rapidamente.
Eu recomendo que você crie uma swift2.0
ramificação e mantenha seu código atualizado usando o XCode 7 beta 5. Você ficará satisfeito com os aprimoramentos do compilador (no entanto, eu diria que o estado global do XCode 7 ainda é lento e com erros)
ATUALIZAÇÃO Com o Xcode 8.2
Já faz um tempo desde a minha última atualização sobre esse problema, então aqui está.
Nosso aplicativo agora tem cerca de 20 mil linhas de código Swift quase exclusivamente, o que é decente, mas não excepcional. Foi submetido à migração rápida 2 e à migração rápida 3. Demora cerca de 5 / 6m para compilar em um Macbook pro de meados de 2014 (Intel Core i7 a 2,5 GHz), o que é bom em uma construção limpa.
No entanto, a construção incremental ainda é uma piada, apesar da Apple alegar que:
O Xcode não reconstruirá um destino inteiro quando apenas pequenas alterações ocorrerem. (28892475)
Obviamente, acho que muitos de nós rimos depois de verificar essa bobagem (adicionar uma propriedade privada (privada!) A qualquer arquivo do meu projeto recompilará a coisa toda ...)
Gostaria de apontar para este tópico nos fóruns de desenvolvedores da Apple, que têm mais algumas informações sobre o problema (além de apreciar a comunicação do desenvolvedor da Apple sobre o assunto de vez em quando)
Basicamente, as pessoas sugerem algumas coisas para tentar melhorar a construção incremental:
- Adicione uma
HEADER_MAP_USES_VFS
configuração de projeto definida comotrue
- Desativar
Find implicit dependencies
do seu esquema - Crie um novo projeto e mova sua hierarquia de arquivos para o novo.
Vou tentar a solução 3, mas a solução 1/2 não funcionou para nós.
O que é ironicamente engraçado em toda essa situação é que, olhando para o primeiro post sobre esse problema, estávamos usando o Xcode 6 com o código swift 1 ou swift 1.1 quando atingimos a lentidão das primeiras compilações e agora cerca de dois anos depois, apesar das melhorias reais da Apple. situação é tão ruim quanto era com o Xcode 6. Que irônico.
Na verdade, eu realmente se arrepender de escolher Swift sobre Obj / C para o nosso projeto por causa da frustração diária que envolve. (Eu até mudo para o AppCode, mas isso é outra história)
De qualquer forma, vejo este post de SO com 32k + visualizações e 143 ups até o momento em que escrevi, então acho que não sou o único. Aguente firme, apesar de serem pessimistas com relação a essa situação, pode haver alguma luz no fim do túnel.
Se você tiver tempo (e coragem!), Acho que a Apple agradece o radar sobre isso.
Até a próxima! Felicidades
ATUALIZAÇÃO Com o Xcode 9
Tropeçar nisso hoje. O Xcode introduziu discretamente um novo sistema de compilação para melhorar o desempenho terrível atual. Você deve habilitá-lo através das configurações da área de trabalho.
Ainda tentei, mas atualizará esta postagem depois que ela terminar. Parece promissor.
Respostas:
Bem, aconteceu que Rob Napier estava certo. Foi um único arquivo (na verdade, um método) que estava causando a falha do compilador.
Agora não me interpretem mal. O Swift recompila todos os seus arquivos a cada vez, mas o melhor agora é que a Apple adicionou feedback de compilação em tempo real sobre os arquivos que compila, então o Xcode 6 GM agora mostra quais arquivos Swift estão sendo compilados e o status da compilação em tempo real como você pode ver nesta captura de tela:
Portanto, é muito útil saber quais arquivos estão demorando tanto. No meu caso, era este pedaço de código:
porque a propriedade
title
era do tipovar title:String?
e nãoNSString
. O compilador estava ficando louco ao adicioná-lo aoNSMutableDictionary
.Alterando para:
fez a compilação passar de 10/15 segundos (talvez até mais) para um único segundo ... incrível.
fonte
Tentamos várias coisas para combater isso, pois temos cerca de 100 mil linhas de código Swift e 300 mil linhas de código ObjC.
Nosso primeiro passo foi otimizar todas as funções de acordo com a saída dos tempos de compilação da função (por exemplo, conforme descrito aqui https://thatthinginswift.com/debug-long-compile-times-swift/ )
Em seguida, escrevemos um script para mesclar todos os arquivos rápidos em um arquivo, isso quebra os níveis de acesso, mas aumentou o tempo de compilação de 5 a 6 minutos para 1 minuto.
Agora isso está extinto, porque perguntamos à Apple sobre isso e eles aconselharam que deveríamos fazer o seguinte:
'Fast, Whole Module Optimization'
'-Onone'
Quando esses sinalizadores são definidos, o compilador compila todos os arquivos Swift em uma etapa. Descobrimos com nosso script de mesclagem que isso é muito mais rápido do que compilar arquivos individualmente. No entanto, sem a
-Onone'
substituição, ele também otimizará todo o módulo, que é mais lento. Quando definimos o'-Onone'
sinalizador nos outros sinalizadores Swift, ele interrompe a otimização, mas não para de compilar todos os arquivos Swift em uma única etapa.Para obter mais informações sobre a otimização de todo o módulo, consulte a publicação no blog da Apple aqui - https://swift.org/blog/whole-module-optimizations/
Descobrimos que essas configurações permitem que nosso código Swift seja compilado em 30 segundos :-) Não tenho evidências de como funcionaria em outros projetos, mas sugiro que tente se os tempos de compilação Swift ainda são um problema para você.
Observe para as compilações da App Store, você deve deixar o
'-Onone'
sinalizador de fora, pois a otimização é recomendada para compilações de produção.fonte
-Onone
. Por enquanto, não podemos usar a otimização de todo o módulo, porque causa uma falha no compilador ... Mas o seu conselho dá quase 10 x de aumento à nossa velocidade de compilação. No MacBook Air (anual de 2013), ele estava construindo cerca de 8 minutos, agora diminui para cerca de 1 minuto e metade do tempo gasto alternando entre alvos (temos aplicativos, extensões e poucas estruturas internas) e compilando storyboards-Onone
ajuda para reduzir os tempos de construção. Muito obrigado companheiro!Provavelmente tem pouco a ver com o tamanho do seu projeto. Provavelmente é algum trecho de código específico, possivelmente apenas uma linha. Você pode testar isso tentando compilar um arquivo por vez, em vez de todo o projeto. Ou tente assistir os logs de compilação para ver qual arquivo está demorando tanto.
Como um exemplo dos tipos de código que podem causar problemas, essa essência de 38 linhas leva mais de um minuto para compilar no beta7. Tudo isso é causado por este bloco:
Simplifique isso com apenas uma ou duas linhas e ele compila quase instantaneamente. O problema é que isso está causando crescimento exponencial (possivelmente fatorial) no compilador. Obviamente, isso não é o ideal, e se você puder isolar essas situações, abra radares para ajudar a limpar esses problemas.
fonte
CompileSwift
fase. Leva todos os arquivos rápidos, mesmo que apenas um tenha sido modificado. Portanto, se for um arquivo que está demorando algum tempo (o que duvido muito), o compilador nunca dirá qual é.swiftc
para ver quanto tempo eles demoram.Se você estiver tentando identificar arquivos específicos que diminuem o tempo de compilação, tente compilá-lo na linha de comando via xctool, que fornecerá os tempos de compilação arquivo por arquivo.
O que deve ser observado é que, por padrão, ele cria 2 arquivos simultaneamente por cada núcleo de CPU e não fornece o tempo decorrido "líquido", mas o tempo absoluto de "usuário". Dessa forma, todos os intervalos entre os arquivos paralelos são parecidos.
Para superar isso, defina o
-jobs
sinalizador como 1 , para que não paralelize as compilações de arquivos. Levará mais tempo, mas no final, você terá tempos de compilação "líquidos" para comparar arquivo por arquivo.Este é um comando de exemplo que deve fazer o truque:
xctool -workspace <your_workspace> -scheme <your_scheme> -jobs 1 build
A saída da fase "Compile Swift files" seria algo como:
Nesta saída, você pode identificar rapidamente quais arquivos estão demorando mais que outros para serem compilados. Além disso, você pode determinar com alta precisão se suas refatorações (conversões explícitas, dicas de tipo, etc ...) estão diminuindo o tempo de compilação para arquivos específicos ou não.
NOTA: tecnicamente, você também pode fazê-lo,
xcodebuild
mas a saída é incrivelmente detalhada e difícil de consumir.fonte
Swift Compiler
→Optimization Level
paraFast, Whole Module Optimization [-O -whole-module-optimization]
No meu caso, o Xcode 7 não fez nenhuma diferença. Eu tinha várias funções exigindo vários segundos para compilar.
Exemplo
Depois de desembrulhar os opcionais, o tempo de compilação caiu 99,4% .
Veja mais exemplos neste post e neste post .
Analisador de tempo de compilação para Xcode
I desenvolveu um plug-in Xcode que pode vir a calhar para qualquer um que experimenta estas questões.
Parece haver melhorias chegando no Swift 3, então esperamos ver nosso código Swift compilar mais rapidamente.
fonte
Provavelmente não podemos consertar o compilador Swift, mas algo que podemos consertar é o nosso código!
Há uma opção escondida no compilador Swift que imprime os intervalos de tempo exatas que compilador leva para compilar cada função:
-Xfrontend -debug-time-function-bodies
. Ele nos permite encontrar gargalos em nosso código e melhorar significativamente o tempo de compilação.Simples, execute o seguinte no terminal e analise os resultados:
Awesome Brian Irace escreveu um artigo brilhante sobre o perfil de seus tempos de compilação Swift .
fonte
alias grep='noglob grep'
primeiro, o grep othewise não funciona #A solução está lançando.
Eu tinha uma enorme variedade de toneladas de dicionários, assim:
Demorou aproximadamente 40 minutos para compilá-lo. Até que eu lancei os dicionários assim:
Isso funcionou para quase todos os outros problemas que encontrei em relação aos tipos de dados codificados no meu aplicativo.
fonte
Uma coisa a observar é que o mecanismo de inferência do tipo Swift pode ser muito lento com os tipos aninhados. Você pode ter uma idéia geral do que está causando a lentidão, observando o log de compilação de unidades de compilação individuais que estão demorando muito tempo e depois copiando e colando o comando completo gerado por Xcode em uma janela do Terminal e pressionando CTRL- \ para obter alguns diagnósticos. Veja http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times para obter um exemplo completo.
fonte
Certifique-se também de que, ao compilar para depuração (Swift ou Objective-C), você defina como Build Active Architecture Only:
fonte
Como todo esse material está na versão beta e como o compilador Swift (pelo menos a partir de hoje) não está aberto, acho que não há resposta real para sua pergunta.
Antes de tudo, comparar o compilador Objective-C ao Swift é de alguma forma cruel. O Swift ainda está na versão Beta, e tenho certeza que a Apple está trabalhando no fornecimento de funcionalidades e na correção de bugs, mais do que na velocidade da luz (você não começa a construir uma casa comprando os móveis). Eu acho que a Apple otimizará o compilador no devido tempo.
Se, por algum motivo, todos os arquivos de origem tiverem que ser compilados completamente, uma opção pode ser criar módulos / bibliotecas separados. Mas essa opção ainda não é possível, pois o Swift não pode permitir bibliotecas até que o idioma esteja estável.
Meu palpite é que eles otimizarão o compilador. Pelo mesmo motivo que não podemos criar módulos pré-compilados, pode ser que o compilador precise compilar tudo do zero. Mas assim que o idioma atingir uma versão estável e o formato dos binários não estiver mais mudando, poderemos criar nossas bibliotecas e talvez (?) O compilador também consiga otimizar seu trabalho.
Mas acho que apenas a Apple sabe ...
fonte
Para o Xcode 8, vá para as configurações do projeto, em Editor> Adicionar configuração de compilação> Adicionar configuração definida pelo usuário e adicione o seguinte:
A adição desse sinalizador reduziu o tempo de compilação de compilação limpa de 7 minutos para 65 segundos para um projeto rápido de 40KLOC, milagrosamente. Também pode confirmar 2 amigos viram melhorias semelhantes em projetos empresariais.
Só posso assumir que isso é algum tipo de bug no Xcode 8.0
Edição: Parece que não funciona mais no Xcode 8.3 para algumas pessoas.
fonte
Infelizmente, o compilador Swift ainda não está otimizado para compilação rápida e incremental (a partir do Xcode 6.3 beta). Enquanto isso, você pode usar algumas das seguintes técnicas para melhorar o tempo de compilação do Swift:
Divida o aplicativo em Frameworks para reduzir o impacto da recompilação. Mas lembre-se de que você deve evitar dependências cíclicas no seu aplicativo. Para mais informações sobre este tópico, verifique este post: http://bits.citrusbyte.com/improving-swift-compile-time/
Use Swift para partes do seu projeto que são bastante estáveis e não mudam frequentemente. Para outras áreas em que você precisa alterar com muita frequência ou áreas que exigem muitas iterações de compilação / execução (quase todas as coisas relacionadas à interface do usuário), use melhor o Objective-C com uma abordagem de combinação e combinação.
Experimente a injeção de código de tempo de execução com 'Injection for Xcode'
Use o método roopc: http://roopc.net/posts/2014/speeding-up-swift-builds/
Alivie o mecanismo de inferência do tipo rápido, dando algumas dicas com elencos explícitos.
fonte
A construção rápida de matrizes e dicionários parece ser uma causa bastante popular para isso (especialmente para você que tem experiência em Ruby ), ou seja,
provavelmente será a causa em que isso deve corrigi-lo:
fonte
Para depuração e teste, use as seguintes configurações para reduzir o tempo de compilação de cerca de 20 minutos para menos de 2 minutos,
Eu perdi inúmeras horas esperando a construção do projeto, apenas para perceber que tinha que fazer uma pequena alteração e tive que esperar mais 30 minutos para testá-lo. Essas são as configurações que funcionaram para mim. (Ainda estou experimentando as configurações)
Porém, certifique-se de definir pelo menos "DWARF com dSYM" (se você deseja monitorar seu aplicativo) e Construir Arquitetura Ativa como "NÃO" para liberação / arquivamento para enviar para o iTunes Connect (lembro-me de desperdiçar algumas horas aqui também).
fonte
Set Build for Active Architecture: YES
me deu uma redução de aproximadamente 45% no tempo de compilação. Muito obrigado.O compilador gasta muito tempo deduzindo e verificando os tipos. Portanto, adicionar anotações de tipo ajuda muito o compilador.
Se você tiver muitas chamadas de funções em cadeia, como
Em seguida, o compilador leva um tempo para descobrir qual
sum
deve ser o tipo . Adicionar o tipo ajuda. O que também ajuda é puxar as etapas intermitentes para variáveis separadas.Especialmente para tipos numéricos
CGFloat
,Int
pode ajudar bastante. Um número literal como2
pode representar muitos tipos numéricos diferentes. Portanto, o compilador precisa descobrir, a partir do contexto, qual é.As funções que levam muito tempo para serem visualizadas
+
também devem ser evitadas. O uso de vários+
para concatenar várias matrizes é lento porque o compilador precisa descobrir qual implementação de+
deve ser chamada para cada uma+
. Portanto, use avar a: [Foo]
comappend()
se possível.Você pode adicionar um aviso para detectar quais funções demoram a compilar no Xcode .
Em Configurações de compilação, para sua pesquisa de destino, selecione Outros sinalizadores Swift e adicione
-Xfrontend -warn-long-function-bodies=100
avisar sobre todas as funções que levam mais de 100 ms para serem compiladas.
fonte
Para os projetos que misturam Objective C e Swift código, podemos definir
-enable-bridging-pch
emOther Swift Flags
. Com isso, o cabeçalho da ponte é analisado apenas uma vez e o resultado (um arquivo temporário de "cabeçalho pré-compilado" ou "PCH") é armazenado em cache e reutilizado em todos os arquivos Swift no destino. A Apple afirmou que diminui o tempo de construção em 30%. Link de referência:NOTA: Isso funciona apenas para o Swift 3.1 e superior.
fonte
A reinicialização do meu Mac fez maravilhas para esse problema. Passei de compilações de 15 minutos para compilações de 30 segundos apenas reiniciando.
fonte
O tempo de compilação rápido foi aprimorado no novo Xcode 6.3
fonte
Aqui está outro caso que pode causar lentidão maciça com inferência de tipo. Operadores de coalescência .
Alterando linhas como:
para
ajudou a trazer o meu tempo de compilação dos anos 70 para 13s
fonte
Nada funcionou para mim no Xcode 6.3.1 - quando adicionei cerca de 100 arquivos Swift, que o Xcode travou aleatoriamente na compilação e / ou indexação. Eu tentei uma opção modular sem sucesso.
Instalar e usar o Xcode 6.4 Beta realmente funcionou para mim.
fonte
Isso tem funcionado como mágica para mim - Speed Up Swift Compilation . Reduziu o tempo de compilação para 3 minutos a partir de 10 minutos.
Ele diz que você deve ligar o
Whole Module Optimization
ao adicionar-Onone
emOther Swift Flags
.Eu estou usando
Swift 3
emXcode 8.3
/Xcode 8.2
.fonte
Misturar literal inteiro e literal float em uma expressão também causa um longo tempo de compilação.
Muitas expressões de 1000 + ms em tempo de compilação são reduzidas para 10 ~ 100ms depois de eu colocar um
.0
literal depois do número inteiro.fonte