Estamos obtendo tempos de compilação muito lentos, que podem levar mais de 20 minutos em máquinas de 2GHz e 2G de núcleo duplo.
Muito disso se deve ao tamanho da nossa solução, que cresceu para mais de 70 projetos, bem como ao VSS, que é um gargalo em si quando você tem muitos arquivos. (trocar o VSS não é uma opção, infelizmente, por isso não quero que isso desça para um bash do VSS)
Estamos olhando para mesclar projetos. Também estamos procurando ter várias soluções para obter uma maior separação de preocupações e tempos de compilação mais rápidos para cada elemento do aplicativo. Isso eu vejo que se tornará um inferno de DLL, à medida que tentamos manter as coisas sincronizadas.
Estou interessado em saber como outras equipes lidaram com esse problema de dimensionamento. O que você faz quando sua base de código atinge uma massa crítica que você está desperdiçando metade do dia assistindo à barra de status entregar mensagens de compilação.
ATUALIZAÇÃO Eu esqueci de mencionar que esta é uma solução C #. Obrigado por todas as sugestões de C ++, mas já faz alguns anos que eu tenho que me preocupar com cabeçalhos.
EDITAR:
Boas sugestões que ajudaram até agora (sem dizer que não há outras boas sugestões abaixo, apenas o que ajudou)
- Novo laptop de 3GHz - o poder da utilização perdida faz maravilhas ao buscar gerenciamento
- Desativar o antivírus durante a compilação
- 'Desconectando' do VSS (na verdade, a rede) durante a compilação - posso remover a integração do VS-VSS por completo e continuar usando a interface do usuário do VSS
Ainda não ronca através de uma compilação, mas tudo ajuda.
Orion mencionou em um comentário que os genéricos também podem ter uma peça. Dos meus testes, parece haver um impacto mínimo no desempenho, mas não alto o suficiente para garantir - os tempos de compilação podem ser inconsistentes devido à atividade do disco. Devido a limitações de tempo, meus testes não incluíram tantos genéricos ou código, como apareceriam no sistema ativo, para que possam acumular-se. Eu não evitaria usar genéricos onde eles deveriam ser usados, apenas para desempenho em tempo de compilação
GAMBIARRA
Estamos testando a prática de criar novas áreas do aplicativo em novas soluções, importando as dlls mais recentes, conforme necessário, integrando-as à solução maior quando estivermos felizes com elas.
Também podemos fazer o mesmo com o código existente, criando soluções temporárias que apenas encapsulam as áreas em que precisamos trabalhar e as descartamos após a reintegração do código. Precisamos ponderar o tempo necessário para reintegrar esse código contra o tempo que ganhamos por não ter Rip Van Winkle como experiências com recompilação rápida durante o desenvolvimento.
fonte
Respostas:
A equipe do Chromium.org listou várias opções para acelerar a compilação (neste momento, na metade da página):
fonte
Temos quase 100 projetos em uma solução e um tempo de compilação do desenvolvedor de apenas alguns segundos :)
Para o desenvolvimento local constrói criamos um Visual Studio suplemento que as mudanças
Project references
paraDLL references
e descarrega os projectos indesejados (e uma opção para mudá-los de volta, claro).Nossas construções agora levam apenas alguns segundos quando estamos trabalhando em apenas alguns projetos por vez. Também podemos depurar os projetos adicionais, pois estão vinculados às DLLs de depuração. A ferramenta normalmente leva de 10 a 30 segundos para fazer um grande número de alterações, mas você não precisa fazer isso com tanta frequência.
Atualização de maio de 2015
O acordo que fiz (nos comentários abaixo) era que eu lançaria o plugin para código aberto se isso interessar bastante. 4 anos depois, ele tem apenas 44 votos (e o Visual Studio agora tem duas versões subseqüentes), portanto, atualmente é um projeto de baixa prioridade.
fonte
Eu tive um problema semelhante em uma solução com 21 projetos e 1/2 milhão de LOC. A maior diferença foi obter discos rígidos mais rápidos. No monitor de desempenho, o ' A Fila de Disco 'aumentaria significativamente no laptop, indicando que o disco rígido era o gargalo da garrafa.
Aqui estão alguns dados para o tempo total de reconstrução ...
1) Laptop, Core 2 Duo 2GHz, unidade de 5400 RPM (não tem certeza do cache. Era o padrão Dell inspiron).
Tempo de reconstrução = 112 segundos.
2) Desktop (edição padrão), Core 2 Duo 2.3Ghz, único cache de 8MB e unidade de 7200RPM.
Tempo de reconstrução = 72 segundos.
3) Desktop Core 2 Duo 3Ghz, único 10000 RPM WD Raptor
Tempo de reconstrução = 39 segundos.
A unidade de 10.000 RPM não pode ser subestimada. Constrói onde significativamente mais rápido, além de tudo o mais, como exibir documentação, o uso do File Explorer foi notado mais rapidamente. Foi um grande aumento de produtividade ao acelerar o ciclo de execução de código.
Dado o que as empresas gastam com os salários dos desenvolvedores, é insano o quanto eles podem gastar comprando, equipando-os com os mesmos PCs usados pela recepcionista.
fonte
Para compilações do C # .NET, você pode usar o .NET Demon . É um produto que assume o processo de criação do Visual Studio para torná-lo mais rápido.
Isso é feito analisando as alterações feitas e construindo apenas o projeto que você realmente alterou, bem como outros projetos que realmente se basearam nas alterações feitas. Isso significa que, se você alterar apenas o código interno, apenas um projeto precisará ser construído.
fonte
Desligue o seu antivírus. Ele adiciona idades ao tempo de compilação.
fonte
Use compilação distribuída. Xoreax IncrediBuild pode cortar o tempo de compilação para baixo a alguns minutos.
Usei-o em uma enorme solução C \ C ++, que geralmente leva de 5 a 6 horas para compilar. O IncrediBuild ajudou a reduzir esse tempo para 15 minutos.
fonte
Instruções para reduzir o tempo de compilação do Visual Studio para alguns segundos
Infelizmente, o Visual Studio não é inteligente o suficiente para distinguir as alterações na interface de um assembly das alterações irrelevantes do corpo do código. Esse fato, quando combinado com grandes soluções interligadas, às vezes pode criar uma tempestade perfeita de 'compilações completas' indesejadas quase toda vez que você altera uma única linha de código.
Uma estratégia para superar isso é desativar as construções automáticas da árvore de referência. Para fazer isso, use o 'Configuration Manager' (Build / Configuration Manager ... e, no menu suspenso Configuração da solução ativa, escolha 'New') para criar uma nova configuração de build chamada 'ManualCompile' que copia da configuração de depuração, mas faça marque a caixa de seleção 'Criar novas configurações de projeto'. Nesta nova configuração de compilação, desmarque todos os projetos para que nenhum deles seja compilado automaticamente. Salve esta configuração pressionando 'Fechar'. Essa nova configuração de compilação é adicionada ao seu arquivo de solução.
Você pode alternar de uma configuração de compilação para outra através da lista suspensa de configuração de compilação na parte superior da tela do IDE (a que geralmente mostra 'Debug' ou 'Release'). Efetivamente, essa nova configuração de compilação do ManualCompile tornará inúteis as opções do menu Compilar para: 'Compilar Solução' ou 'Reconstruir Solução'. Portanto, quando você está no modo ManualCompile, deve criar manualmente cada projeto que está modificando, o que pode ser feito clicando com o botão direito do mouse em cada projeto afetado no Solution Explorer e selecionando 'Build' ou 'Rebuild'. Você deve ver que o tempo total de compilação agora será meros segundos.
Para que essa estratégia funcione, é necessário que o VersionNumber encontrado nos arquivos AssemblyInfo e GlobalAssemblyInfo permaneça estático na máquina do desenvolvedor (não durante as compilações da versão, é claro) e que você não assine suas DLLs.
Um risco potencial de usar essa estratégia do ManualCompile é que o desenvolvedor pode esquecer de compilar os projetos necessários e, quando inicia o depurador, obtém resultados inesperados (não é possível anexar o depurador, arquivos não encontrados, etc.). Para evitar isso, provavelmente é melhor usar a configuração de compilação 'Debug' para compilar um esforço maior de codificação e usar apenas a configuração de compilação ManualCompile durante o teste de unidade ou para fazer alterações rápidas com escopo limitado.
fonte
Se for C ou C ++, e você não estiver usando cabeçalhos pré-compilados, você deve estar.
fonte
Tínhamos mais de 80 projetos em nossa solução principal, que levaram de 4 a 6 minutos para serem construídos, dependendo do tipo de máquina que um desenvolvedor estava trabalhando. Consideramos que isso era muito longo: para cada teste, isso realmente destrói seus ETIs.
Então, como obter tempos de construção mais rápidos? Como você já sabe, é o número de projetos que realmente prejudicam o tempo de construção. É claro que não queríamos nos livrar de todos os nossos projetos e simplesmente jogar todos os arquivos de origem em um. Porém, tínhamos alguns projetos que poderíamos combinar: como todo "projeto de repositório" na solução tinha seu próprio projeto mais unido, simplesmente combinamos todos os projetos mais unidos em um projeto globalmente unido. Isso reduziu o número de projetos com cerca de 12 projetos e economizou 40% do tempo para criar toda a solução.
Estamos pensando em outra solução.
Você também tentou configurar uma nova (segunda) solução com um novo projeto? Esta segunda solução deve simplesmente incorporar todos os arquivos usando pastas de solução. Porque você pode se surpreender ao ver o tempo de criação dessa nova solução com apenas um projeto.
No entanto, trabalhar com duas soluções diferentes levará alguma consideração cuidadosa. Os desenvolvedores podem estar inclinados a realmente trabalhar na segunda solução e negligenciar completamente a primeira. Como a primeira solução com mais de 70 projetos será a solução que cuida da sua hierarquia de objetos, essa deve ser a solução em que seu servidor de compilação deve executar todos os seus unittests. Portanto, o servidor para integração contínua deve ser o primeiro projeto / solução. Você precisa manter sua hierarquia de objetos, certo.
A segunda solução com apenas um projeto (que criará muito mais rápido) será o projeto em que o teste e a depuração serão realizados por todos os desenvolvedores. Você precisa cuidar deles olhando para o servidor de compilação! Se algo quebrar, DEVE ser corrigido.
fonte
Verifique se suas referências são referências de projeto e não diretamente para as DLLs nos diretórios de saída da biblioteca.
Além disso, configure-os para não copiar localmente, exceto onde for absolutamente necessário (o projeto EXE principal).
fonte
Postei esta resposta originalmente aqui: /programming/8440/visual-studio-optimizations#8473 Você pode encontrar muitas outras dicas úteis nessa página.
Se você estiver usando o Visual Studio 2008, poderá compilar usando o sinalizador / MP para criar um único projeto em paralelo. Eu li que esse também é um recurso não documentado no Visual Studio 2005, mas nunca tentei.
Você pode criar vários projetos em paralelo usando o sinalizador / M, mas isso geralmente já está definido com o número de núcleos disponíveis na máquina, embora isso se aplique apenas ao VC ++, acredito.
fonte
Percebo que essa pergunta tem muito tempo, mas o tópico ainda é interessante hoje. O mesmo problema me incomodou ultimamente, e as duas coisas que melhoraram o desempenho da compilação foram (1) usar um disco dedicado (e rápido) para compilar e (2) usar a mesma pasta de saída para todos os projetos e definir CopyLocal como False no projeto referências.
Alguns recursos adicionais:
fonte
Algumas ferramentas de análise:
ferramentas-> opções-> configurações do projeto VC ++ -> Tempo de Compilação = Sim informará o tempo de compilação para cada vcproj.
Adicione a
/Bt
opção à linha de comando do compilador para ver quanto levou cada arquivo CPPUsar
/showIncludes
para capturar inclusões aninhadas (arquivos de cabeçalho que incluem outros arquivos de cabeçalho) e ver quais arquivos poderiam economizar muito IO usando declarações de encaminhamento.Isso o ajudará a otimizar o desempenho do compilador, eliminando dependências e monopolizações de desempenho.
fonte
Antes de gastar dinheiro para investir em discos rígidos mais rápidos, tente montar seu projeto inteiramente em um disco RAM (supondo que você tenha memória RAM de sobra). Você pode encontrar vários drivers de disco RAM gratuitos na rede. Você não encontrará nenhuma unidade física, incluindo SSDs, mais rápida que um disco RAM.
No meu caso, um projeto que levou 5 minutos para ser construído em um i7 de 6 núcleos em uma unidade SATA de 7200 RPM com o Incredibuild foi reduzido em apenas 15 segundos usando um disco RAM. Considerando a necessidade de recopilar para armazenamento permanente e o potencial de perda de trabalho, 15 segundos não são incentivos suficientes para usar um disco RAM e provavelmente não são muitos incentivos para gastar várias centenas de dólares em uma unidade SSD ou alta RPM.
O pequeno ganho pode indicar que a compilação foi vinculada à CPU ou que o cache de arquivos do Windows foi bastante eficaz, mas como os dois testes foram realizados a partir de um estado em que os arquivos não foram armazenados em cache, eu me inclino fortemente para compilações associadas à CPU.
Dependendo do código real que você está compilando, sua milhagem pode variar. Portanto, não hesite em testar.
fonte
Qual é o tamanho do seu diretório de compilação após fazer uma compilação completa? Se você seguir a configuração padrão, todo assembly que você criar copiará todas as DLLs de suas dependências e de suas dependências, etc. para o diretório bin. No trabalho anterior, ao trabalhar com uma solução de ~ 40 projetos, meus colegas descobriram que, de longe, a parte mais cara do processo de compilação era copiar esses assemblies repetidamente, e que um compilação podia gerar gigabytes de cópias das mesmas DLLs repetidamente. mais uma vez.
Aqui estão alguns conselhos úteis de Patrick Smacchia, autor do NDepend, sobre o que ele acredita que deve e não deve ser uma assembléia separada:
http://codebetter.com/patricksmacchia/2008/12/08/advices-on-partitioning-code-through-net-assemblies/
Existem basicamente duas maneiras de contornar isso, e ambas têm desvantagens. Uma é reduzir o número de montagens, o que obviamente é muito trabalhoso. Outra é reestruturar seus diretórios de compilação para que todas as suas pastas bin sejam consolidadas e os projetos não copiem as DLLs de suas dependências - eles não precisam, porque já estão todos no mesmo diretório. Isso reduz drasticamente o número de arquivos criados e copiados durante uma compilação, mas pode ser difícil de configurar e pode deixar você com alguma dificuldade em extrair apenas as DLLs exigidas por um executável específico para empacotamento.
fonte
Talvez pegue algumas funções comuns e crie algumas bibliotecas, para que as mesmas fontes não sejam compiladas repetidamente para vários projetos.
Se você estiver preocupado com a mistura de diferentes versões de DLLs, use bibliotecas estáticas.
fonte
Desative a integração do VSS. Você pode não ter a opção de usá-lo, mas as DLLs são renomeadas "acidentalmente" o tempo todo ...
E definitivamente verifique suas configurações de cabeçalho pré-compiladas. O guia de Bruce Dawson é um pouco antigo, mas ainda muito bom - confira: http://www.cygnus-software.com/papers/precompiledheaders.html
fonte
Eu tenho um projeto que tem 120 ou mais exes, bibliotecas e dlls e leva um tempo considerável para construir. Eu uso uma árvore de arquivos em lote que chamam de criar arquivos a partir de um arquivo em lotes mestre. Eu tive problemas com coisas estranhas de cabeçalhos incrementais (ou foram temperamentais) no passado, então eu os evito agora. Eu faço uma compilação completa com pouca frequência e geralmente a deixo até o final do dia enquanto dou uma caminhada por uma hora (para que eu possa imaginar que leva cerca de meia hora). Então, eu entendo por que isso não é viável para trabalhar e testar.
Para trabalhar e testar, tenho outro conjunto de arquivos em lote para cada aplicativo (ou módulo ou biblioteca) que também possui todas as configurações de depuração em vigor - mas elas ainda chamam os mesmos arquivos de criação. Eu posso ativar e desativar DEBUG de tempos em tempos e também decidir sobre compilações ou marcas ou se eu também quero criar bibliotecas das quais o módulo possa depender, e assim por diante.
O arquivo em lotes também copia o resultado concluído nas (ou várias) pastas de teste. Dependendo das configurações, isso é concluído em alguns segundos a um minuto (em vez de dizer meia hora).
Eu usei um IDE (Zeus) diferente, pois gosto de ter controle sobre coisas como arquivos .rc e, na verdade, prefiro compilar a partir da linha de comando, mesmo que eu esteja usando o MS compliers.
É um prazer postar um exemplo desse arquivo em lotes, se alguém estiver interessado.
fonte
Desabilite a indexação do sistema de arquivos nos diretórios de origem (especificamente nos diretórios obj, se você desejar que a fonte seja pesquisável)
fonte
Se esse for um aplicativo Web, definir a compilação em lote como true pode ajudar, dependendo do cenário.
Você pode encontrar uma visão geral aqui: http://weblogs.asp.net/bradleyb/archive/2005/12/06/432441.aspx
fonte
Você também pode procurar referências de projeto circulares. Foi um problema para mim uma vez.
Isso é:
O Projeto A faz referência ao Projeto B
O projeto B faz referência ao projeto C
O Projeto C faz referência ao Projeto A
fonte
Uma alternativa mais barata ao Xoreax IB é o uso do que eu chamo de compilações de arquivos uber. É basicamente um arquivo .cpp que possui
Então você compila as unidades uber em vez dos módulos individuais. Vimos tempos de compilação de 10 a 15 minutos até 1 a 2 minutos. Talvez seja necessário experimentar quantas #includes por arquivo uber fazem sentido. Depende dos projetos. etc. Talvez você inclua 10 arquivos, talvez 20.
Você paga um custo, então cuidado:
É meio doloroso, mas para um projeto que é amplamente estático em termos de novos módulos, o sofrimento inicial pode valer a pena. Eu já vi esse método vencer o IB em alguns casos.
fonte
Se for um projeto C ++, você deve usar cabeçalhos pré-compilados. Isso faz uma enorme diferença nos tempos de compilação. Não tenho certeza do que o cl.exe realmente está fazendo (sem usar cabeçalhos pré-compilados), parece estar procurando muitos cabeçalhos STL em todos os lugares errados antes de finalmente ir para o local correto. Isso adiciona segundos inteiros a todos os arquivos .cpp que estão sendo compilados. Não tenho certeza se este é um bug do cl.exe ou algum tipo de problema STL no VS2008.
fonte
Olhando para a máquina em que você está construindo, ela está configurada de maneira ideal?
Acabamos de reduzir o tempo de criação do nosso maior produto em escala corporativa C ++, de 19 horas para 16 minutos , garantindo a instalação do driver de filtro SATA correto.
Sutil.
fonte
Há uma opção / documento não documentado no Visual Studio 2005, consulte http://lahsiv.net/blog/?p=40 , que permitiria a compilação paralela com base em arquivos e não em projetos. Isso pode acelerar a compilação do último projeto ou, se você compilar um projeto.
fonte
Ao escolher uma CPU: o tamanho do cache L1 parece ter um enorme impacto no tempo de compilação. Além disso, geralmente é melhor ter 2 núcleos rápidos do que 4 lentos. O Visual Studio não usa os núcleos extras de maneira muito eficaz. (Baseei isso na minha experiência com o compilador C ++, mas provavelmente também é verdade para o C #.)
fonte
Agora também estou convencido de que há um problema com o VS2008. Estou executando-o em um laptop Intel dual core com 3G Ram, com o antivírus desligado. A compilação da solução geralmente é bastante eficiente, mas se eu estiver depurando, uma recompilação subsequente geralmente fica lenta para um rastreamento. Fica claro pela luz contínua do disco principal que há um gargalo de E / S do disco (você também pode ouvi-lo). Se eu cancelar a compilação e o desligamento do VS, a atividade do disco será interrompida. Reinicie o VS, recarregue a solução e depois reconstrua, e é muito mais rápido. Unitl da próxima vez
Penso que este é um problema de paginação de memória - o VS fica sem memória e o sistema operacional inicia a troca de páginas para tentar ganhar espaço, mas o VS está exigindo mais do que a troca de páginas pode oferecer, por isso diminui a velocidade de rastreamento. Não consigo pensar em outra explicação.
Definitivamente o VS não é uma ferramenta RAD, é?
fonte
Por acaso, sua empresa usa o Entrust para sua solução de PKI / Criptografia? Acontece que estávamos tendo um desempenho péssimo na compilação de um site bastante grande construído em C #, levando mais de 7 minutos em um Rebuild-All.
Minha máquina é um i7-3770 com 16 GB de RAM e um SSD de 512 GB, portanto, o desempenho não deve ter sido tão ruim. Percebi que meus tempos de compilação eram incrivelmente mais rápidos em uma máquina secundária mais antiga, construindo a mesma base de código. Então, iniciei o ProcMon nas duas máquinas, criei um perfil das compilações e comparei os resultados.
Eis que a máquina de desempenho lento tinha uma diferença - uma referência ao Entrust.dll no rastreamento de pilha. Usando essas informações recém-adquiridas, continuei pesquisando o StackOverflow e encontrei o seguinte: MSBUILD (VS2010) muito lento em algumas máquinas . De acordo com a resposta aceita, o problema está no fato de o manipulador Entrust estar processando as verificações de certificado .NET em vez do manipulador nativo da Microsoft. Também é sugerido que o Entrust v10 resolva esse problema predominante no Entrust 9.
No momento, eu o desinstalei e meus tempos de compilação caíram para 24 segundos . YYMV com o número de projetos que você está construindo no momento e pode não resolver diretamente o problema de dimensionamento sobre o qual estava perguntando. Postarei uma edição nesta resposta se puder fornecer uma correção sem recorrer à desinstalação do software.
fonte
É certo que há um problema com o VS2008. Porque a única coisa que fiz foi instalar o VS2008 para atualizar meu projeto que foi criado com o VS2005. Eu só tenho 2 projetos na minha solução. Não é grande. Compilação com o VS2005: 30 segundos Compilação com o VS2008: 5 minutos
fonte
Boas sugestões que ajudaram até agora (sem dizer que não há outras boas sugestões abaixo, se você estiver com problemas, recomendo a leitura, apenas o que nos ajudou)
Ainda não ronca através de uma compilação, mas tudo ajuda.
Também estamos testando a prática de criar novas áreas do aplicativo em novas soluções, importando as dlls mais recentes, conforme necessário, integrando-as à solução maior quando estivermos felizes com elas.
Também podemos fazer o mesmo com o código existente, criando soluções temporárias que apenas encapsulam as áreas em que precisamos trabalhar e as descartamos após a reintegração do código. Precisamos ponderar o tempo necessário para reintegrar esse código contra o tempo que ganhamos por não ter Rip Van Winkle como experiências com recompilação rápida durante o desenvolvimento.
Orion mencionou em um comentário que os genéricos também podem ter uma peça. Dos meus testes, parece haver um impacto mínimo no desempenho, mas não alto o suficiente para garantir - os tempos de compilação podem ser inconsistentes devido à atividade do disco. Devido a limitações de tempo, meus testes não incluíram tantos genéricos ou código, como apareceriam no sistema ativo, para que possam acumular-se. Eu não evitaria usar genéricos onde eles deveriam ser usados, apenas para desempenho em tempo de compilação
fonte