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
,但这并不总是令人满意的。
答案 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
也被设置为最长。