为什么D编译需要这么长时间?

时间:2011-12-26 12:30:54

标签: compilation d

D是编译速度最快的编程语言之一,如果不是最快的话,但情况并非总是如此。当unittest开启时,事情变得非常缓慢。我目前的项目有6-7个模块(~2000 LOC),每个模块都有单元测试,也包含基准测试。以下是我当前项目中的一些数字:

dmd -O -noboundscheck需要0m1.287s

dmd -O -release -noboundscheck需要0m1.382s

dmd -O -inline -noboundscheck需要0m1.499s

dmd -O -inline -release -noboundscheck需要0m3.477s

-unittest添加到上述任何一个都会大大增加编译时间:

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

有时会崩溃DMD:

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

显然,unittest是错误的,但同时它已成为我项目的重要组成部分。我想知道减速是否正常还是正在进行的工作?我的项目正在不断发展,每一个新的单元测试都需要更长时间的编译。我知道的唯一解决方案是禁用-release-inline,但这并不总是令人满意的。

3 个答案:

答案 0 :(得分:4)

DMD有一个已知的优化问题:long blocks of code optimise with an O(n^2) algorithm,因此使用优化进行编译需要很长时间。

尝试将代码拆分为较小的函数,同时应该获得更好的编译时间。您可以使用内联函数轻松完成此操作:

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

将其转换为:

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

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

这对我有用。

答案 1 :(得分:1)

非常小的性能改进可能是通过version(unittest) block将模板实例化移动到模块范围,例如:

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

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

unittest {
    auto x = fooInt(1);
}

对此进行分析,如果我通过~30msec在5000个等效单位测试块中使用别名模板实例,我可以提高auto x = fooInt(1)速度,相比之下,通过auto x = foo(1)直接在每个单元测试块中实例化它(这实际上扩展为auto x = foo!int(1))。

这可能仅适用于您有大量单元测试创​​建相同模板实例的情况。

答案 2 :(得分:0)

我确实替换了很多通用代码,但它只减少了4-5秒的编译时间。事情变得更糟,我相信编译器可能是问题所在:

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

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

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

当设置-O-inline-release-unittest时,编译时间最长。删除-O会大大减少编译时间。因此,为了减少单元测试时的编译时间,请删除优化标志。对于正常的编译,您可以使用三个中的任何一个(-inline-release-unittest)。根据我的经验,这三者的组合导致编译时间最长,而-unittest也被设置为最长。