2009-04-02 11 views
9

Tenemos un proyecto que usa gcc y make files. El proyecto también contiene un gran subproyecto (SDK) y una gran cantidad de subproyectos relativamente pequeños que usan ese SDK y algún marco compartido.GCC/Make Build Time Optimizations

Utilizamos encabezados precompilados, pero eso solo ayuda a que la recompilación sea más rápida.

¿Existen técnicas y herramientas conocidas para ayudar con las optimizaciones de tiempo de compilación? ¿O tal vez conoces algunos artículos/recursos sobre este o temas relacionados?

Respuesta

14

Puede resolver el problema desde dos lados: refactorizar el código para reducir la complejidad que está viendo el compilador o acelerar la ejecución del compilador.

Sin tocar el código, puede agregar más potencia de compilación. Use ccache para evitar recompilar archivos que ya ha compilado y distcc para distribuir el tiempo de compilación entre más máquinas. Utilice make -j donde N es el número de núcleos + 1 si compila localmente, o un número mayor para compilaciones distribuidas. Esa bandera ejecutará más de un compilador en paralelo.

Refacturación del código. Prefiere la declaración directa a incluye (simple). Desacople todo lo que pueda para evitar dependencias (use la expresión idiomática PIMPL).

La instanciación de plantillas es costosa, se recompilan en cada unidad de compilación que las utiliza. Si puede refactorizar sus plantillas para reenviarlas, puede declararlas y luego crear instancias en una sola unidad de compilación.

6

Lo mejor que puedo pensar con make es la opción -j. Esto le dice a make ejecutar tantos puestos de trabajo como sea posible en paralelo:

make -j

Si desea limitar el número de trabajos simultáneos a n puede utilizar:

make -jn


Asegúrate de que las dependencias sean correctas para que make no ejecute los trabajos que realiza no tienes que hacerlo


Otra cosa a tener en cuenta es que las optimizaciones gcc hace con el interruptor -O. Puede especificar varios niveles de optimización. Cuanto mayor sea la optimización, más largos serán los tiempos de compilación y enlace. Un proyecto con el que trabajo se ejecuta en 2 minutos para vincularse con -O3, y medio minuto con -O1. Debes asegurarte de que no estás optimizando más de lo necesario. Puede construir sin optimización para compilaciones de desarrollo y con optimización para compilaciones de implementación.


Compilar con información de depuración (gcc -g) probablemente aumentará el tamaño de su ejecutable y puede afectar su tiempo de construcción. Si no lo necesita, intente eliminarlo para ver si le afecta.


El tipo de enlace (estático frente a dinámico) debería marcar la diferencia. Por lo que yo entiendo, la vinculación estática toma más tiempo (aunque puedo estar equivocado aquí). Debería ver si esto afecta su compilación.

+0

También asegúrese de que se realice cualquier recursión para que make -j realmente funcione. Por ejemplo, no hay llamadas "make -Cdirir", use $ (MAKE), etc. – richq

+0

No estoy seguro de entender la sugerencia. –

+2

Si sus archivos make recurren llamando solo make, no obtendrá mucha escalabilidad con -j ya que solo el nivel superior hará uso de -j arg, debería usar $ (MAKE) porque invocará submakes con el mismo - j y tendrá una mejor oportunidad para ejecutar todos los trabajos. –

0

Si tiene una LAN con máquinas de desarrollo, quizás deba intentar implementar una solución de compilador distribuido, como distcc.

Esto puede no ser de ayuda si todo el tiempo durante la compilación se utiliza analizando dependencias o realizando una única tarea en serie. Para el crujido crudo de la compilación de muchos archivos fuente en archivos objeto, la construcción paralela obviamente ayuda, como lo sugiere (en una sola máquina) Nathan. La paralelización en varias máquinas puede llevarlo aún más lejos.

0

http://ccache.samba.org/ acelera a lo grande.

Trabajo en un proyecto de tamaño medio, y eso es lo único que hacemos para acelerar el tiempo de compilación.

+2

Siempre y cuando no hagas un truco estúpido con __DATE __/__ TIME__ o macros relacionadas, ccache es bueno para acelerar compilaciones limpias repetidas. Por otro lado, si haces construcciones limpias a menudo, significa que tu sistema de reconstrucción está roto y debes arreglarlo primero ... – ephemient

2

Si tiene varias computadoras disponibles, gcc está bien distribuido por distcc.

Además, también puede usar ccache.

Todo esto funciona con muy pocos cambios en los makefiles.

4

De la descripción del proyecto supongo que tiene un Makefile por directorio y está utilizando mucho hacer recursivo. En ese caso, las técnicas de "Recursive Make Considered Harmful" deberían ser de gran ayuda.

2

Además, es probable que desee mantener sus archivos de código fuente lo más pequeños y autónomos posible/factibles, es decir, prefiera muchos archivos de objetos más pequeños en un solo archivo de objeto único.

Esto también ayudará a evitar recompilaciones innecesarias, además puede tener una biblioteca estática con archivos de objetos para cada directorio o módulo de código fuente, básicamente permitiendo que el compilador reutilice la mayor cantidad posible de código compilado previamente.

Algo más, que aún no se mencionaba en ninguna de las respuestas anteriores, hace que los enlaces de símbolos sean 'privados', es decir, prefiere enlaces estáticos (funciones, variables) para su código si no es necesario ser visible externamente

Además, es posible que también desee examinar el uso del GNU gold linker, que es much more efficient para compilar el código C++ para objetivos ELF.

Básicamente, te aconsejo que perfile cuidadosamente su proceso de construcción y verifique dónde se gasta el mayor tiempo, que le dará algunas sugerencias sobre cómo optimizar su proceso de construcción o la estructura de código fuente de su proyecto.

0

Puede usar el compilador distribuido distcc para reducir el tiempo de compilación si tiene acceso a varias máquinas. He aquí un artículo a partir de IBM developerWorks relacionados con distcc y cómo puede utilizarlo: http://www.ibm.com/developerworks/linux/library/l-distcc.html

Otro método para reducir el tiempo de construcción es el uso de encabezados precompilados. Aquí hay un starting point for gcc.

Además, no olvide utilizar -j al compilar con make si su máquina tiene más de una CPU/núcleo (2x el número de núcleos/cpus está bien).

2

Podría considerar cambiar a un sistema de compilación diferente (que obviamente no funcionará para todos), como SCons. SCons es mucho más inteligente que make. Escanea automáticamente las dependencias del encabezado, por lo que siempre tendrá el conjunto más pequeño de dependencias de reconstrucción.Al agregar la línea Decider('MD5-timestamp') a su archivo SConstruct, SCons primero verá la marca de tiempo de un archivo, y si es más reciente que la marca de tiempo construida previamente, usará el MD5 del archivo para asegurarse de que realmente haya cambiado algo. Esto funciona no solo en los archivos fuente sino también en los archivos de objetos. Esto significa que si cambia un comentario, por ejemplo, no tiene que volver a vincularlo.

El escaneo automático de archivos de encabezado también ha asegurado que nunca tenga que escribir scons --clean. Siempre hace lo correcto.

0

El uso de archivos pequeños puede no ser siempre una buena recomendación. Un disco tiene un tamaño de sector de 32 o 64 K min, con un archivo que toma al menos un sector. Así que 1024 archivos de tamaño 3K (código pequeño en el interior) realmente tomarán 32 o 64 Meg en el disco, en lugar de los 3 megas esperados. 32/64 meg que debe leer el disco. Si los archivos están dispersos en el disco, aumenta el tiempo de lectura aún más con el tiempo de búsqueda. Esto se ayuda con Disk Cache, obviamente, hasta el límite. El encabezado precompilado también puede ayudar a aliviar esto.

Por lo tanto, respetando las pautas de codificación, no tiene sentido salir de ellas simplemente para colocar cada strcuct, typedef o clase de utilidad en archivos separados.