2009-05-04 10 views
17

mia situazioneCome diminuire i tempi di MSBuild

Nel progetto C# Ora sto lavorando su abbiamo una abbastanza grande soluzione di (80 + progetti). Ora i tempi di ricostruzione di 5 minuti + stanno diventando davvero un problema usando MSBuild da Visual Studio 2008.

In un'analisi ho fatto la scorsa settimana si è scoperto che il mio tempo di costruzione è stato speso nel modo seguente:

  1. Copiare i file dei progetti e ricopiare per i progetti che dipendono da esso (CopyToLocal), ecc . (60%)

  2. Invocazione di un postbuild da decompilare/compilare. (20%)

  3. Fare la compilazione vera e propria, ecc (20%)

A parte i 'normali' del progetto bin\debug cartelle uscita viene copiato anche ad una directory esterna per impostare il principale ' loader '. La struttura del programma principale è un po 'come questo:

\loader\bin\loader.exe 

\loader\plugin\plugin1\plugin1.dll 

\loader\plugin\plugin1\somedependency.dll 

Quello che ho fatto

Nel tentativo di rendere le cose vanno un po' più veloce ho pensato di quanto segue:

  1. Copy tutti i file in una directory big bin e non utilizzare CopyTolocal. Non mi piace perché non possiamo più utilizzare versioni diverse degli stessi file DLL e la mia directory bin sta diventando un bel pasticcio.

  2. Use parallelism (/m) for MSBuild. Questo aiuta solo pochissimo nei tempi di costruzione.

  3. Provare a ridurre le dipendenze tra i progetti che è sempre una buona cosa, ovviamente.

  4. Investire in hardware. Ho trovato alcuni research on solid-state drives, ma questo non sembra promettente.

La mia domanda

Ho anche notato che quando faccio una modifica a un progetto che è alla radice del mio albero delle dipendenze tutto diventa ricostruire. Anche se il cambiamento era solo nella parte "privata" e l'interfaccia del progetto non è cambiata.

MSBuild utilizza un timestamp di progetti dipendenti per determinare se un progetto richiede una ricostruzione?

Può essere modificato in una condizione diversa? Ad esempio, il checksum del file?

Oltre a questo suggerimento specifico, sicuramente apprezzerei tutti i suggerimenti per velocizzare i tempi di costruzione.

+0

Possibile duplicato di [Miglioramento del tempo di creazione dell'elemento della configurazione (.NET)] (http://stackoverflow.com/questions/8633313/improving-ci-build-time-net) –

risposta

3

Abbiamo anche soluzioni enormi. La compilazione e la compilazione riguardano tutto l'I/O.

Le unità a stato solido sono molto promettenti. Un collega di lavoro ha messo un'unità a stato solido nel suo laptop e ha scoperto che ora è molto più veloce della sua enorme scatola di sviluppo principale. Non avere i dettagli, ma afferma molte volte più velocemente.

Siamo stati giocherellare con cartelle soluzione per raggruppare parti del progetto: Questo rende più facile per gli sviluppatori di progetti scaricamento non stanno lavorando.

/m raramente aiuta con .NET debug build. Ho fatto una serie di test su questo alcune settimane fa e ho trovato differenze minori. Risultati:

  • Perché la mia build è di I/O costretto, utilizzando /m: 2-4 fa build di debug più lento per me.
  • Generalmente le build di rilascio sono molto più veloci.
  • L'analisi del codice aggiunge molto tempo.

Big picture: In realtà, la compilazione è un costo piuttosto basso per me, rispetto a ottenere test di unità sorgente e in esecuzione. Sul nostro server di build, i test di integrazione e il packaging sono quasi sempre. Per la mia casella di sviluppo, pianifico un file batch che ottiene origine, crea, esegue test unitari prima di venire a lavoro e mentre sono a pranzo. Abbastanza buono.

Sul server di build, è più complicato. Stiamo pensando di creare build paralleli concatenati CruiseControl.NET su varie macchine. Stiamo usando VSTS build, ma è troppo costoso (e richiede tempo) per ridimensionare orizzontalmente come questo.

I miei numeri per persone orientate ai dettagli. Configurazioni dal più lento al più veloce, eseguendo msbuild "bigsolution.sln"/target: pulito - tra ciascuna.

  1. /m: 4, debug con analisi del codice 1:38
  2. /m: 1, debug con analisi del codice 1:30
  3. /m: 4, debug senza analisi del codice 1:30
  4. /m: 1, debug senza analisi del codice 1:30
  5. /m: 1, versione con analisi del codice: 1:30
  6. /m: 4, versione con analisi del codice: 1:05
  7. /m: 4, Rilascio senza analisi del codice: 0:53

Tempo di costruzione, senza ricostruire o puliti: ~ 4-10 secondi

+0

grazie per la risposta. Potrei esaminare un po 'di più le unità Solid State. Il tempo di costruzione è un grosso problema per me dal momento che mi piace usare TDD e creare un LOT;) –

1

MSBuild costruire il tempo è un problema multidimensionale. La buona notizia è che è facile da risolvere:

A differenza della maggior parte dei processi in esecuzione sulla macchina di compilazione, i processi di generazione sono noti per il consumo di CPU, RAM e I/O. Una ricetta generale per accelerare MSBuild costruisce è "ottenere la migliore macchina da soldi può comprare", in particolare:

  1. CPU - almeno due Intel 3,0 GHz Core 2 Duo.

  2. RAM: almeno 4 GB DDR3. Se si tratta di uno sviluppatore e build machine, un sistema operativo a 64 bit e 8   GB RAM è un'opzione migliore.

  3. HDD - Le opzioni più veloci sono un RAID-1 3ware high-end con una batteria integrata e una cache di scrittura abilitata. Un SSD veloce può essere un'altra opzione da considerare.

  4. Rete - minimo 1   Scheda Gbit/s.

Questa semplice ottimizzazione dell'hardware può velocizzare i tuoi MSBuilds 2-3 volte.

22

Sto lavorando su progetti di applicazioni 500+ C#. I progetti sono compilati in parallelo e copylocal impostato su false. Il tempo di compilazione è di circa 37   min senza test di unità e copertura del codice. 13   min per la creazione incrementale senza modifiche nel codice.

Se spengo la compilazione parallela e imposta il copylocale su vero, il tempo di compilazione è superiore a 1   h 40   min.

Ho una configurazione diversa per build locale, build di check-in gated e build di server con fase di implementazione (build notturne).

Qui sono le mie esperienze: i file di output

  1. Copia ad una directory non è buona idea se si vuole costruire i vostri progetti in parallelo senza CopyLocal impostata su false. I miei assembly sono stati a volte bloccati quando più progetti hanno fatto riferimento allo stesso assembly e MSBuild ha provato a copiare questo riferimento nella cartella di output nello stesso momento. This solution è stato molto utile per me. Ho impostato copylocal su false per tutti i riferimenti e la dimensione della directory di build è stata ridotta di 10 volte (10 volte meno I/O). Ho un setup diverso per la build locale e per la build del server. Configurazione diversa per la build di check-in gated e per la build di distribuzione completa.
  2. Se abilito la creazione parallela, le build sono più veloci, molto più veloci. Se si dispone di un server di build potente, la build /m:2 dovrebbe essere 2x più veloce come build /m:1. Non ha nulla a che fare con le dipendenze tra i progetti (se copylocal è impostato su false).
  3. È necessario ridurre le dipendenze tra i progetti se si desidera avere una build incrementale rapida. Non ha alcun impatto su una build completa (falsa copylocale). Il tempo di compilazione incrementale dipende dalla posizione del progetto modificata nella struttura di build.

Sì, MSBuild utilizza un timestamp di progetti dipendenti per determinare se un progetto richiede una ricostruzione. Confronta i file di input (file di codice, assiemi di riferimento, file temporanei, ..) timestamp con l'assembly di output. Se qualcosa è cambiato, il tuo progetto viene ricompilato. Cerca di ridurre il numero di dipendenze tra i progetti per ridurre al minimo la ricompilazione. Se la modifica era solo nella parte "privata" del progetto, l'assembly di output verrà modificato, la data/ora di assemblaggio verrà modificata e anche tutti i progetti correlati verranno ricostruiti. Non puoi fare molto con questo.

Eseguire la compilazione due volte con la verbosità diagnostica senza alcuna modifica nel codice e controllare "Costruire obiettivo" CoreCompile "completamente" come descritto here. Puoi avere qualcosa di sbagliato nei tuoi file di progetto e ogni volta i tuoi progetti vengono ricompilati. Se non si modifica nulla, il registro di build non deve contenere log "Building target" CoreCompile "completamente".

Il nostro server di build è una macchina virtuale, non un vero pezzo di hardware. Non è una buona idea usare una VM per un server di build, ma non è stata una mia decisione.

Se si dispone di RAM multi-GB, provare a utilizzarne una parte come disco rigido in memoria. La tua build dovrebbe essere molto più veloce :)

Le unità SSD sono sensibili agli alti I/O al giorno. Ha un impatto sulla garanzia.

Spero che aiuta qualcuno ...;)

+0

Come si eseguono i test di unità/integrazione? Avevo bisogno di impostare copylocal su true per i test, quindi tutte le DLL necessarie sono nella cartella bin di test. Hai trovato la soluzione per non aver bisogno di farlo? – ya23

+0

AggiungiTrue a tutti i tag Reverence e ProjectReference nei progetti di test dell'unità. – Ludwo

+0

Posso farlo e andrà bene, ma non sarò in grado di eseguire test. NET cerca i binari dipendenti nella cartella di dll che viene testata. Ho letto di probing e DEVPATH, ma non sembrano abbastanza buoni - i problemi sorgono quando si costruiscono sia il debug che il rilascio. Mettere tutte le DLL necessarie in GAC funzionerebbe, ma suona pazzesco e non è comunque un'opzione. – ya23

0

Se hai abbastanza RAM e utilizza Visual C++ (non è sicuro su C#), si potrebbe accelerare le cose copiando tutto include e lib ad una RAM guidare.

È anche possibile posizionare gli elementi di costruzione temporanei sull'unità RAM. Certo, hai bisogno di una grande quantità di RAM. Un'unità RAM da 2 GB sarebbe sufficiente per gli include e le librerie. Ma per i file temporanei (* .obj, ecc.) Dipenderebbe dal progetto. Quindi potrebbe essere tra 1 e 4   GB in più o più.

+0

In che modo * si * imposta * una RAM? –