【问题标题】:Why does D compilation take so long?为什么D编译需要这么长时间?
【发布时间】:2011-12-26 12:30:53
【问题描述】:

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,但这并不总是可取的。

【问题讨论】:

  • 你的单元测试中有很多模板实例化吗?
  • @Cyber​​Shadow 是的,它主要是模板实例化,因为有很多通用编程。
  • 这很可能是原因。尝试将代码的非通用部分移到模板之外。
  • @Cyber​​Shadow 没有非通用代码。
  • @Arlen,我认为他的意思是尝试通过只制作真正通用的部分来减少通用代码的数量,通用。通常,您可以通过从模板中提取出实际上不需要模板化的代码片段来缓解问题。即使您将此类代码分解为可以更频繁地重用的较小模板,它也会有所帮助。

标签: compilation d


【解决方案1】:

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();
}

这对我有用。

【讨论】:

  • 我想你的意思是嵌套函数?
【解决方案2】:

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

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

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

unittest {
    auto x = fooInt(1);
}

对此进行分析,如果我通过 auto x = fooInt(1) 在 5000 个等效的单元测试块中使用别名模板实例,则与通过 auto x = foo(1) 直接在每个单元测试块中实例化它相比,我得到了 ~30msec 速度改进(这实际上扩展为 @ 987654326@).

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

【讨论】:

  • 模板或通用代码似乎不是问题。它确实减少了编译时间,但总的来说这不是问题。我重构了我的代码,只注意到了 4-6 秒的差异。考虑到它只有 2k 行代码,它仍然非常慢。它与优化有关。
  • 我个人在单元测试时不使用-release。 `-release- 摆脱了我可能拥有的任何断言,这些断言可能会使我的单元测试在不应该通过时通过。
  • @AndrejM。只要你用-unittest编译,断言就不会被删除,即使你用-release编译。
  • 有趣,我不知道。
【解决方案3】:

我确实替换了大部分通用代码,但它只将编译时间缩短了 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 时也是最长的。

【讨论】:

    猜你喜欢
    • 2010-09-24
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    相关资源
    最近更新 更多