Pregunta

Me parece que si hay una gran cantidad de clases el tiempo de compilación se incrementa drásticamente cuando se utiliza un solo * .h y uno * archivo .cpp por clase. Ya utilizo encabezados precompilados y la vinculación incremental, pero aún así el tiempo de compilación es muy largo (sí utilizo impulso;)

Así me ocurrió con el siguiente truco:

  • definidos archivos * .cpp como no compilables
  • definidos como archivos * .CXX compilables
  • añade un archivo * .cxx por aplicación módulo, y #include todos los archivos .cpp * de este módulo en el mismo.

Así que en lugar de más de 100 unidades de traducción que terminó con sólo 8 unidades de traducción. El tiempo de compilación se convirtió en 4-5 veces más corto.

Las desventajas son que usted tiene que incluir manualmente todos los archivos * .cpp (pero no es realmente una pesadilla de mantenimiento ya que si se olvida de incluir algo que el enlazador le recordará), y que algunas comodidades VS IDE no está trabajando con este esquema, por ejemplo, Ir a / Mover a la implementación etc.

Así que la pregunta es, es tener una gran cantidad de unidades de traducción CPP realmente el único camino verdadero? Es mi truco de un patrón conocido, o tal vez me falta algo? Gracias!

¿Fue útil?

Solución

El concepto se llama acumulación

Otros consejos

Una desventaja importante de este enfoque es causada por tener un archivo .obj para cada unidad de traducción.

Si crea una biblioteca estática para su reutilización en otros proyectos en los que a menudo se enfrentan a los binarios más grandes en esos proyectos si tiene varias unidades de traducción enormes en vez de muchos pequeños porque el vinculador sólo incluirá los archivos .obj que contiene las funciones / variables realmente hace referencia dentro del proyecto utilizando la biblioteca.

En el caso de grandes unidades de traducción que es más probable que cada unidad se hace referencia y se incluye en el archivo .obj correspondiente. binarios grandes pueden ser un problema en algunos casos. También es posible que algunos conectores son lo suficientemente inteligentes como para incluir sólo las funciones / variables necesarias, no toda los archivos .obj.

Además, si el archivo .obj está incluido y todas las variables globales están incluidos también entonces sus constructores / destructores serán llamados cuando se inicia el programa / parado que sin duda llevará tiempo.

He visto lo que se hace en los videojuegos, ya que ayuda a que el compilador para hacer optimizaciones que de otro modo no podría hacer, así como ahorrar una gran cantidad de memoria. He visto "acumulación súper" y "construcción a granel" se refieren a esta idea. Y si ayuda a acelerar su acumulación, por qué no ..

Sujeción de un mayor número de archivos de código fuente de C ++ en un solo archivo es un enfoque que se ha mencionado un par de veces recientemente, especialmente cuando las personas estaban construyendo sistemas grandes y tirando en los archivos de cabecera complicadas (que va a ser impulso, a continuación) .

Como se menciona VS, he encontrado que el número de archivos de inclusión en un proyecto y en especial el tamaño de la ruta de inclusión parece afectar Visual C ++ 's tiempos de compilación mucho más de lo que hace g ++' s tiempos de compilación. Este es especialmente el caso con una gran cantidad de anidado incluye (de nuevo, hace que el impulso) que sean necesarios para encontrar todos los archivos de inclusión requeridas por el código fuente de un gran número de búsquedas de archivos. Combinando el código en un único archivo de origen significa que el compilador puede ser mucho más inteligente sobre la búsqueda de dicho incluye, además de que hay, obviamente, menos de ellos que se encuentran como se puede esperar que los archivos en el mismo subproyecto sería probable que incluya una muy similar un conjunto de archivos de cabecera.

El "gran cantidad de unidades de compilación" para el desarrollo C ++ por lo general proviene de un deseo de desacoplar las clases y minimizar las dependencias entre clases por lo que el compilador sólo tiene que reconstruir el conjunto mínimo de archivos en caso de realizar cualquier cambio. Esto es generalmente un buen enfoque, pero a menudo no es realmente factible en un subproyecto simplemente porque los archivos allí tienen dependencias entre sí por lo que va a terminar con bastante grandes reconstrucciones de todos modos.

No creo que la reducción del número de unidades de compilación es una buena idea. Su están tratando de resolver un problema con el tiempo gran compilación, y este enfoque parece ayudar con él, pero lo que se obtiene, además:

  1. Aumento del tiempo de compilación durante el desarrollo. Por lo general, desarrollador modificar algunos archivos a la vez, y la compilación será probablemente más rápido para 3-4 archivos pequeños a continuación, para un archivo muy grande.
  2. Como se ha mencionado, más difícil de navegar código, en mi humilde opinión esto es extremadamente importante.
  3. Puede tener alguna interferencia entre archivos .cpp incluido en un archivo .cxx:

    a. Es una práctica común para definir localmente en cpp (para versiones de depuración) nueva macro para comprobación de fugas de memoria. Lamentablemente, esto no se puede hacer antes de incluir los encabezados usando la colocación de nuevo (como algunos encabezado STL y aumentar hacer)

    b. Es una práctica común añadir utilizando declaraciones en cpp. Con su enfoque de esto puede conducir a problemas con cabeceras, incluida más adelante

    c. conflictos de nombres son más probables

En mi humilde opinión, mucho más limpio (pero manera tal vez más caro) para acelerar el tiempo de compilación es utilizar algún sistema de generación distribuida. Son especialmente eficaces para la limpieza construye.

No estoy seguro si esto es relevante en su caso, pero tal vez se puede utilizar en lugar de declaración definición de reducir el número de #include 's que usted tiene que hacer. Además, tal vez se puede usar el lenguaje pimpl para el mismo propósito. Eso sería la esperanza de reducir el número de archivos de origen que es necesario volver a compilar cada vez y el número de cabeceras que han de ser tirado en.

unidades más grandes y menos de traducción no se aprovechan de la compilación en paralelo. No sé lo que los compiladores y qué plataformas está utilizando, pero la compilación en múltiples unidades de traducción paralelas podría disminuir significativamente el tiempo de construcción ...

A raíz de sharptooths post, me tienden a examinar los ejecutables resultantes en algún detalle. Si son diferentes, me tienden a limitar su técnica para versiones de depuración y el recurso a la configuración original para el proyecto principal versión de lanzamiento. Al comprobar el ejecutable, también me miro su uso huella de memoria y recursos en el arranque y durante la ejecución.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top