2011-12-26 14 views
10

D es uno de los lenguajes de programación más rápidos para compilar, si no el más rápido, pero este no es siempre el caso. Las cosas se vuelven extremadamente lentas cuando unittest está encendido. Mi proyecto actual tiene 6-7 módulos (~ 2000 LOC), con cada uno de ellos con pruebas unitarias que también contienen puntos de referencia. Aquí están algunos números de mi proyecto actual:¿Por qué tarda tanto la compilación D?

dmd -O -noboundscheck toma 0m1.287s

dmd -O -release -noboundscheck toma 0m1.382s

dmd -O -inline -noboundscheck toma 0m1.499s

dmd -O -inline -release -noboundscheck toma 0m3.477s

añadiendo -unittest a cualquiera de la voluntad por encima aumentar drásticamente compi tiempo mento:

dmd -O -inline -release -noboundscheck -unittest toma 0m21.918s

ya veces se bloquea DMD:

time dmd -O t1.d -inline -noboundscheck -version=Double -unittest toma 0m2.297s Internal error: ../ztc/gdag.c 776

evidentemente, unittest está libre de errores, pero al mismo tiempo se ha convertido en una parte importante de mi proyecto. Me gustaría saber si la desaceleración es normal o ¿se está trabajando en algo? Mi proyecto está creciendo y con cada nueva prueba unitaria, la compilación tarda más y más. La única solución que conozco es desactivar -release y -inline, pero eso no siempre es deseable.

+0

¿Tiene muchas instancias de plantilla en las pruebas de su unidad? –

+0

@CyberShadow Sí, se trata principalmente de instancias de plantillas porque hay mucha programación genérica. – Arlen

+0

Esa es probablemente la razón. Intente mover las partes no genéricas de su código fuera de las plantillas. –

Respuesta

1

una mejora muy pequeña rendimiento podría ser mover instancias de plantilla al módulo de alcance, a través de un version(unittest) block, por ejemplo:

auto foo(T)(T t) { return t; } 

version(unittest) { 
    alias foo!int fooInt; 
} 

unittest { 
    auto x = fooInt(1); 
} 

Perfilado esto, consigo alrededor ~30msec mejora de la velocidad si uso la instancia de plantilla alias en 5000 bloques de prueba unitarios equivalentes a través de auto x = fooInt(1), en comparación con instanciarlo directamente en cada bloque de prueba de unidad a través de auto x = foo(1) (esto en realidad se expande a auto x = foo!int(1)).

Esto probablemente solo funcione en los casos en los que tenga muchos unittest que creen la misma instancia de plantilla.

+0

plantillas o código genérico no parece ser el problema. Reduce el tiempo de compilación, pero en general no es el problema. Refactoreé mi código y solo noté una diferencia de 4 a 6 segundos. Todavía es muy lento considerando el hecho de que son solo 2k líneas de código. Tiene algo que ver con la optimización. – Arlen

+0

Personalmente, no uso '-release' cuando pruebas la unidad. '-release- se deshace de cualquier afirmación que pueda tener, lo que podría hacer que mis unittest pasen cuando no deberían. –

+1

@AndrejM. Siempre que compile con '-unittest', las aserciones no se eliminan, incluso si compila con' -release'. –

4

DMD tiene un problema conocido con las optimizaciones: long blocks of code optimise with an O(n^2) algorithm, por lo que las funciones largas tardan mucho tiempo en compilarse con optimizaciones.

Intenta dividir el código en funciones más pequeñas y, mientras tanto, deberías obtener mejores tiempos de compilación. Esto se puede hacer fácilmente mediante el uso funciones en línea:

void foo() 
{ 
    // lots of code 
    // more code 
} 

convertir esto en:

void foo() 
{ 
    void block1() 
    { 
     // lots of code 
    } 
    block1(); 

    void block2() 
    { 
     // more code 
    } 
    block2(); 
} 

Esto funcionó para mí.

+0

Creo que te refieres a funciones anidadas? –

0

Reemplacé gran parte de mi código genérico, pero solo redujo el tiempo de compilación entre 4 y 5 segundos.Las cosas han empeorado, y creo que el compilador es probablemente el tema:

time dmd -O -inline -release -noboundscheck -unittest toma 0m30.388s

time dmd -O -inline -release -noboundscheck toma 0m11.597s

time dmd -inline -release -noboundscheck -unittest toma 0m1.884s

Cuando -O, -inline, -release y -unittest son todo listo, la compilación lleva más tiempo. La caída de -O reduce drásticamente el tiempo de compilación. Por lo tanto, para reducir el tiempo de compilación durante la prueba unitaria, suelte los indicadores de optimización. Para compilaciones normales, puede usar cualquiera de los tres (-inline, -release, -unittest) sin problema. En mi experiencia, es la combinación de los tres lo que hace que la compilación tome el segundo más largo, y la más larga cuando también se establece -unittest.

Cuestiones relacionadas