Articulo de referencia

Unidad de compilación única

La unidad de compilación única ( SCU , por sus siglas en inglés) es una técnica de programación para los lenguajes C y C++ que reduce el tiempo de compilación de programas que a...

La unidad de compilación única ( SCU , por sus siglas en inglés) es una técnica de programación para los lenguajes C y C++ que reduce el tiempo de compilación de programas que abarcan varios archivos. Específicamente, permite que el compilador conserve los datos de los archivos de cabecera, definiciones y plantillas compartidas, evitando así tener que recrearlos para cada archivo. Se trata de una optimización de programas y puede considerarse una forma de implementar la programación modular . Esta técnica puede aplicarse a un programa completo o a un subconjunto de archivos fuente; cuando se aplica a un programa completo, también se conoce como compilación unitaria . [ 1 ]

Objetivo

En el modelo de compilación de C/C++ (formalmente "entorno de traducción"), los archivos fuente individuales .c / .cpp se preprocesan en unidades de traducción , que luego el compilador compila por separado en múltiples archivos objeto ( .o o .obj ). Estos archivos objeto se pueden enlazar para crear un único archivo ejecutable o biblioteca. Sin embargo, esto conlleva múltiples pasadas sobre archivos de cabecera comunes y, en C++, múltiples instanciaciones de las mismas plantillas en diferentes unidades de traducción.

La técnica de unidad de compilación única utiliza directivas de preprocesador para "unir" diferentes unidades de traducción en tiempo de compilación en lugar de en tiempo de enlace. Esto reduce el tiempo de compilación general, debido a la eliminación de la duplicación, pero aumenta el tiempo de compilación incremental (el tiempo requerido después de hacer un cambio en cualquier archivo fuente individual que se incluye en la SCU), debido a que se requiere una recompilación completa de toda la unidad si cambia cualquier archivo de entrada individual. [ 2 ] Por lo tanto, esta técnica es apropiada para un conjunto de archivos fuente modificados con poca frecuencia con una superposición significativa (muchos o costosos encabezados o plantillas comunes), o archivos fuente que requieren recompilación conjunta con frecuencia, como debido a que todos incluyen un encabezado o plantilla común que cambia con frecuencia. [ 3 ] Es similar al uso de encabezados precompilados , que son ideales para encabezados que cambian muy raramente o nunca, o módulos de C++ (que se agregaron en C++20 ).

Otra desventaja de SCU es que es secuencial, compilando todos los archivos fuente incluidos en un solo proceso, por lo que no se puede paralelizar, como sí se puede hacer con la compilación por separado (mediante distcc o programas similares). Por lo tanto, SCU requiere una partición explícita (particionamiento manual o "fragmentación" en varias unidades) para paralelizar la compilación.

SCU también permite que un compilador optimizador realice optimización interprocedimental sin necesidad de optimización en tiempo de enlace , lo que permite optimizaciones como la inserción en línea y ayuda a evitar la inflación implícita del código debido a excepciones , efectos secundarios y asignación de registros . Estas optimizaciones a menudo no son posibles en muchos compiladores, debido a la compilación independiente, donde la optimización se realiza por separado en cada unidad de traducción durante la compilación, pero el "enlazador tonto" simplemente enlaza los archivos objeto, sin realizar ninguna optimización por sí mismo, y por lo tanto la optimización interprocedimental entre unidades de traducción no es posible.

Ejemplo

Por ejemplo, supongamos que existen los archivos fuente Foo.cpp y Bar.cpp ; estos se pueden colocar en una única unidad de compilación de la siguiente manera:

#incluir "Foo.cpp" #incluir "Bar.cpp"

Supongamos que Foo.cpp y Bar.cpp son:

// Foo.cpp #include <iostream> // Un archivo de cabecera grande y estándar #include "Bar.h" // Declaración de la clase 'Bar'// Definición completa de la clase Foo aquí class Foo : public Bar { public : // ... };// Definición de la función 'main' int main () { Foo foo ; foo . qux (); }
// Bar.cpp #include <iostream> // El mismo encabezado grande y estándar#include "Bar.h" // contenido de la declaración de la clase Barbarra vacía ::qux () const noexcept { // ... }

Ahora el archivo de encabezado estándar ( <iostream>) se compila solo una vez, y la clase Bary Bar::qux()pueden insertarse en línea en la función main(), a pesar de provenir de otro archivo fuente.

Véase también

Referencias

  1. Desarrollador, Unicorn (25-12-2017). "Acelerando la compilación de proyectos C y C++" . Medium . Consultado el 16-03-2022 .
  2. Krajewski, Marek (31 de enero de 2019). Programación práctica de alto rendimiento con Qt 5: Cree aplicaciones multiplataforma utilizando concurrencia, programación paralela y gestión de memoria . Packt Publishing Ltd. ISBN 978-1-78953-330-9.
  3. Schach (1992-05-19). Ingeniería práctica de software . CRC Press. pág. 183. ISBN  978-0-256-11454-6.