Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does D compilation take so long?

Tags:

compilation

d

D is one of the fastest programming languages to compile, if not the fastest, but this isn't always the case. Things become painfully slow when unittest is turned on. My current project has 6-7 modules (~2000 LOC), with every single one of them having unittests that also contain benchmarks. Here are some numbers from my current project:

dmd -O -noboundscheck takes 0m1.287s

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

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

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

adding -unittest to any one of the above will drastically increase compilation time:

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

and sometimes it crashes DMD:

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

Evidentially, unittest is buggy but at the same time it has become an important part of my project. I would like to know if the slowdown is normal or is it something that's being worked on? My project is growing and with every new unittest the compilation is taking longer and longer. The only solution I know is to disable -release and -inline, but that's not always desirable.

like image 654
Arlen Avatar asked Dec 26 '11 12:12

Arlen


2 Answers

DMD has a known issue with optimisations: long blocks of code optimise with an O(n^2) algorithm, so long functions take a long time to compile with optimisations.

Try splitting your code up into smaller functions and you should get better compile times in the meantime. You can do this quite easily by using inline functions:

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

Turn this into:

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

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

This worked for me.

like image 66
Peter Alexander Avatar answered Dec 23 '22 11:12

Peter Alexander


A very tiny performance improvement could be to move template instantiation to module-scope, via a version(unittest) block, e.g.:

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

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

unittest {
    auto x = fooInt(1);
}

Profiling this, I get around ~30msec speed improvement if I use the aliased template instance in 5000 equivalent unittest blocks via auto x = fooInt(1), compared to instantiating it directly in each unittest block via auto x = foo(1) (this actually expands to auto x = foo!int(1)).

This will likely only work for cases where you have a lot of unittests that create the same template instance.

like image 28
Andrej Mitrović Avatar answered Dec 23 '22 10:12

Andrej Mitrović