2009-05-04 15 views
17

mi situación¿Cómo disminuir los tiempos de MSBuild

En el proyecto de C# Ahora estoy trabajando en una solución que tienen bastante grande (más de 80 proyectos). Ahora los tiempos de reconstrucción de 5 minutos + se están convirtiendo en un gran problema al utilizar MSBuild desde Visual Studio 2008.

En un análisis que hizo la semana pasada resultó que mi tiempo de construcción se pasó de la siguiente manera:

  1. Copia de archivos a los proyectos y volver a copiar a los proyectos que dependen de ella (CopyToLocal), etc. . (60%)

  2. Invocando una postconstrucción para descompilar/compilar. (20%)

  3. Haciendo la compilación real, etc. (20%)

Aparte de los 'normales' del proyecto bin\debug carpetas de salida también se copia en un directorio externo para configurar el principal ' programa cargador '. La estructura principal del programa es un poco como esto:

\loader\bin\loader.exe 

\loader\plugin\plugin1\plugin1.dll 

\loader\plugin\plugin1\somedependency.dll 

Lo que hice

En un intento de hacer que las cosas van un poco más rápido que pensé lo siguiente:

  1. Copiar todos los archivos a uno son un directorio grande y no usan CopyTolocal. No me gusta esto porque ya no puedo usar diferentes versiones de los mismos archivos DLL y mi directorio bin se está volviendo un desastre.

  2. Use parallelism (/m) for MSBuild. Esto ayuda muy poco en los tiempos de construcción.

  3. Trate de reducir las dependencias entre proyectos, que siempre es una buena cosa, por supuesto.

  4. Invertir en hardware. Encontré algunos research on solid-state drives, pero esto no parece prometedor.

Mi pregunta

También he notado que cuando hago un cambio en un proyecto que está en la raíz de mi árbol de dependencias todo consigue reconstruir. Incluso si el cambio fue solo en la parte 'privada' y la interfaz del proyecto no cambió.

¿Utiliza MSBuild una marca de tiempo de proyectos dependientes para determinar si un proyecto necesita una reconstrucción?

¿Se puede cambiar esto a una condición diferente? Por ejemplo, la suma de comprobación del archivo?

Aparte de esta sugerencia específica, agradecería todas las sugerencias para acelerar los tiempos de compilación.

+0

Posible duplicado de [Mejora del tiempo de construcción de CI (.NET)] (http://stackoverflow.com/questions/8633313/improving-ci-build-time-net) –

Respuesta

3

También tenemos soluciones enormes. La compilación y compilación se trata de I/O.

Las unidades de estado sólido son muy prometedoras. Un compañero de trabajo puso una unidad de estado sólido en su computadora portátil, y descubrió que ahora es mucho más rápido que su enorme caja de desarrollo principal. No tiene los detalles, pero afirma muchas veces más rápido.

Hemos estado jugando con carpetas solución a agrupar partes del proyecto: Esto hace que sea más fácil para los desarrolladores a proyectos Unload no están trabajando en.

/m rara vez ayuda con las versiones de depuración .NET. Realicé una serie de pruebas sobre esto hace unas semanas y encontré diferencias menores. Hallazgos:

  • Debido a que mi construcción es de E/S obligado, usando /m: 2-4 hace versiones de depuración más lenta para mí.
  • Las versiones de lanzamiento suelen ser mucho más rápidas.
  • El análisis de código agrega mucho tiempo.

Big picture: En realidad, la compilación es un costo bastante menor para mí, en comparación con la obtención de pruebas de unidad de origen y ejecución. En nuestro servidor de compilación, las pruebas de integración y el empaquetado son casi todo el tiempo. Para mi caja de desarrollo, programo un archivo por lotes que obtiene fuente, compilaciones, ejecuta pruebas unitarias antes de venir a trabajar y mientras estoy en el almuerzo. Suficientemente bueno.

En el servidor de compilación, es más complicado. Estamos pensando en instalar construcciones en paralelo encadenadas CruiseControl.NET en varias máquinas. Estamos utilizando la construcción de VSTS, pero es demasiado costoso (y consume mucho tiempo) escalar horizontalmente de esta manera.

Mis números para personas orientadas al detalle. Configuraciones del más lento al más rápido, ejecutando msbuild "bigsolution.sln"/target: clean - entre cada uno.

  1. /m: 4, de depuración con análisis de código 1:38
  2. /m: 1, de depuración con análisis de código 1:30
  3. /m: 4, de depuración sin análisis de código 1:30
  4. /m: 1, de depuración sin análisis de código 1:30
  5. /m: 1, versión con análisis de código: 1:30
  6. /m: 4, versión con análisis de código: 1:05
  7. /m: 4, versión sin análisis de código: 0:53

tiempo de construcción sin reconstruir o limpias: ~ 4-10 segundos

+0

gracias por su respuesta. Podría ver un poco más las unidades de estado sólido. El tiempo de compilación es un gran problema para mí, ya que me gusta usar TDD y crear MUCHO;) –

1

MSBuild tiempo es un problema multidimensional. La buena noticia es que es fácil de resolver:

A diferencia de la mayoría de los procesos que se ejecutan en la máquina de compilación, los procesos de compilación son notorios por consumir CPU, RAM y E/S. Una receta general para acelerar MSBuild construye es "obtener la mejor máquina de dinero puede comprar", en particular:

  1. CPU - al menos dos procesadores Intel de 3,0 GHz Core 2 Duo.

  2. RAM - al menos 4 GB DDR3. Si se trata de una máquina de desarrollo y, un sistema operativo de 64 bits y 8   GB de RAM es una mejor opción.

  3. HDD: la opción más rápida es un 3ware RAID-1 de gama alta con una batería incorporada y una memoria caché de escritura habilitada. Un SSD rápido puede ser otra opción a considerar.

  4. Red - mínimo 1   Tarjeta Gbit/s.

Esta sencilla optimización de hardware puede acelerar sus MSBuilds 2-3 veces.

22

Estoy trabajando en más de 500 proyectos de aplicaciones C#. Los proyectos se compilan en paralelo y copylocal se establece en falso. El tiempo de compilación es de aproximadamente 37   min sin pruebas unitarias y cobertura de código. 13   min para compilación incremental sin ningún cambio en el código.

Si desactivo la compilación paralela y configuro copylocal en verdadero, el tiempo de compilación es de 1   h 40   min.

Tengo una configuración diferente para compilación local, construcciones de compilación con check-in y compilaciones de servidor con implementación de fase (compilaciones nocturnas).

Éstos son mis experiencias: los archivos de salida

  1. Copia de un directorio no es buena idea si usted quiere construir sus proyectos en paralelo sin CopyLocal establece en false. Mis ensamblados a veces se bloquearon cuando varios proyectos hicieron referencia al mismo ensamblado y MSBuild intentó copiar esta referencia a la carpeta de salida al mismo tiempo. This solution fue muy útil para mí. Configuré copylocal en falso para todas las referencias y mi tamaño de directorio de compilación se redujo 10 veces (10 veces menos E/S). Tengo una configuración diferente para la compilación local y para la compilación del servidor. Configuración diferente para la compilación de check-in cerrada y para la compilación de implementación completa.
  2. Si habilito la compilación paralela, las compilaciones son más rápidas, mucho más rápidas. Si tiene un servidor de compilación sólido, su compilación /m:2 debería ser 2 veces más rápida que una compilación /m:1. No tiene nada que ver con las dependencias entre proyectos (si copylocal está establecido en falso).
  3. Debe reducir las dependencias entre los proyectos si desea tener una compilación incremental rápida. No tiene impacto en una compilación completa (copylocal falso). El tiempo de compilación incremental depende de la ubicación del proyecto modificado en el árbol de compilación.

Sí, MSBuild utiliza una marca de tiempo de proyectos dependientes para determinar si un proyecto necesita una reconstrucción. Compara los archivos de entrada (archivos de código, ensambles referenciados, archivos temporales, ...) marca de tiempo con ensamblaje de salida. Si algo cambia, su proyecto se vuelve a compilar. Intente reducir el número de dependencias entre proyectos para minimizar la recompilación. Si su cambio fue solo en la parte 'privada' del proyecto, su ensamblaje de salida cambiará, la marca de tiempo del ensamblaje cambiará y todos los proyectos relacionados se reconstruirán también. No puedes hacer mucho con esto.

Ejecute su compilación dos veces con la verbosidad de diagnóstico sin ningún cambio en su código y verifique que "Construya el objetivo" CoreCompile "completamente" como describí here. Puede tener algo mal en sus archivos de proyecto y sus proyectos se vuelven a compilar todo el tiempo. Si no cambia nada, su registro de compilación no debe contener registros de "completamente" de "compilación de destino" CoreCompile.

Nuestro servidor de compilación es una máquina virtual, no una pieza de hardware real. No es una buena idea usar una VM para un servidor de compilación, pero no fue una decisión mía.

Si tiene RAM de varios GB, intente utilizar parte de ella como un disco duro en memoria. Su compilación debería ser mucho más rápida :)

Las unidades SSD son sensibles a las altas E/S por día. Tiene un impacto en la garantía.

espero que ayude a alguien ...;)

+0

¿Cómo se ejecutan las pruebas de unidad/integración? Necesitaba establecer copylocal en true para las pruebas, por lo que todas las DLL requeridas están en la carpeta de la bandeja de pruebas. ¿Has encontrado una solución para no necesitar hacer eso? – ya23

+0

Agregue Verdadero a todas las etiquetas Reverencia y ProyectoReferencia en sus proyectos de prueba de unidad. – Ludwo

+0

Puedo hacerlo y se compilará muy bien, pero no podré ejecutar pruebas: .NET busca binarios dependientes en la carpeta de dll que se está probando. He leído sobre sondeos y DEVPATH, pero no me parecen lo suficientemente buenos: surgen problemas al compilar Debug and Release. Poner todas las dlls requeridas en GAC funcionaría, pero suena loco y no es una opción de todos modos. – ya23

0

Si usted tiene suficiente memoria RAM y está utilizando Visual C++ (no estoy seguro sobre C#), que podría acelerar las cosas mediante la copia del conjunto incluir y lib a una RAM manejar.

También puede colocar los elementos de compilación temporal para que estén en la unidad RAM. Por supuesto, necesitas una gran cantidad de RAM. Una unidad RAM de 2 GB sería suficiente para los includes y las bibliotecas. Pero para los archivos temporales (* .obj, etc.) dependería del proyecto. Por lo tanto, podría ser entre 1 y 4   GB adicionales o más.

+0

¿Cómo * realmente * configura una unidad RAM? –

Cuestiones relacionadas