加速构建d目标文件

原文
LDC:通过缓存目标文件加速增量构建

为了加快总编译时间,LDC1.1.0可创建目标文件缓存,第二次编译过程中,成功查找缓存时,可跳过优化和构建机器代码,从而显著减少编译时间.

在大型代码基上测试,总构建时间从~3m30(空缓存)减少到~2m30(无更改,所有缓存命中).只需要传递-ir2obj-cache=/tmp/ldccacheLDC,然后如下:

并行构建

编译D程序速度很快.这是它的卖点之一.我第一次编译DMD+druntime+Phobos(整个编译器和标准库)时,它太快了,以至于我以为它在某个地方失败了!

使用DMD编译很快.LDC没有那么快,但它构建的代码比DMD好得多.更好的优化是有代价的.特别是对优化构建(-O3),优化和构建机器代码占据了LDC总执行时间的最大份额.

D编译速度非常快,一般一次编译所有内容就足够了.但对较大项目,拆分为多个并行线程来构建是加快构建速度的好方法.按多个目标文件编译项目,这些文件构建结束时,再链接在一起形成可执行文件.

并行构建过程,更改由许多其他人导入的文件中的一些代码,并重启构建(增量构建)编译导致大量重新.

所有导入修改后文件的文件都需要重新编译,因为构建系统只看到已更改导入的文件,但不知道是否只是"本地"更改(如,在非模板函数中更改12)还是会影响导入文件模块的非本地更改(如更改模板).

如果更改是本地的,则不必重新编译一堆文件,因为构建的目标文件与以前相同.用它来加速增量构建.

优化如下:一旦知道输出与之前目标文件完全相同,就跳过进一步编译,只使用以前目标文件.更通用一点:一旦知道输出与较早输出相同,就中止并使用较早输出.

优化还加快了非并行非单目标构建的速度,因为每个模块都按单独目标文件编译.

编译步骤和查找缓存

这些是ldc的编译步骤:
1,解析输入文件模块;
2,语义分析所有模块;
3,对每个模块,执行:
a.构建LLVMIR(构建IR代码);
b.运行LLVM优化趟;
c.输出目标文件(LLVM机器代码构建);
4,可选:把所有输出目标文件链接到可执行文件中.

可在分析语义后,判断输出是否会与以前相同.分析语义后,编译器知道足够信息来识别每个模块输出.
必须计算一个(几乎)唯一标识目标文件输出的"哈希".重新编译后,重新计算哈希并检查以前是否见过该哈希.当识别哈希时,使用先前构建的目标文件并跳过3b3c步骤.

没有明确定义也不是简单序化语义分析的"输出"(修饰的AST),因此很难计算出好哈希.
但是,构建的LLVMIR(3a步骤),它的定义非常明确,可用LLVMIR序化来计算哈希.只需要构建的LLVMIR(加上-O3等编译标志),就可创建目标文件,并用它来避免与AST更改相关的错误哈希.

新的编译步骤是:
1,按模块解析输入文件;
2,语义分析所有模块;
3,对每个模块,执行:
a.构建LLVMIR(构建IR代码);
b.计算IR哈希并查找缓存.命中缓存时,使用缓存目标文件并继续下个模块.
c.运行LLVM优化趟;
d.输出目标文件(构建LLVM机器代码);
e.在缓存中,按键使用b步骤中计算的哈希存储目标文件.
4,可选:把所有输出目标文件链接到可执行文件中.

关于计算哈希的更多信息

哈希是使用LLVMMD5哈希器计算的.直接喂送LLVM二进制位码表示到哈希器中.其他哈希输入包括编译器版本,LLVM版本和更改目标文件输出(如优化级别和目标CPU)的命令行标志.

-g-d-version=Demo的命令行标志不用于哈希;在3a步骤中的构建LLVMIR外,此类标志没有影响.

可对所有项目使用相同缓存;且可与多个用户共享缓存.

更改代码转为更改哈希

但是,用相同目标文件输出,对两个LDC调用找到哈希差并不难.此D代码可解决问题:

version (FIRST)
{
    int foo(int a)
    {
        return a + 2;
    }
}
else
{
    int foo(int differentname)
    {
        return differentname + 2;
    }
}

用和不用-d-version=FIRST的编译输出导致带不同哈希的相同目标文件.

或:

version (FIRST)
{
    void foo();
    void bar();
}
else
{
    void bar();
    void foo();
}

用法

要从缓存目标文件中受益,只需传递-ir2obj-cache命令行标志给LDC:

ldc2 -ir2obj-cache=/tmp/ldccache

/tmp/ldccache中存储(ircache_.o)缓存文件.

有时需要缓存过期/修剪方案.缓存修剪可由LDC(#1753)使用--ir2obj-cache-prune完成,也可用ldc-prune-cache独立工具访问.

修剪考虑缓存文件上次访问时间,并试保持最近访问文件不变.默认最小修剪间隔为20分钟,这表明如果你试在上一次修剪后的20分钟内修剪,则不会有事情.

可轻松传递--ir2obj-cache-pruneLDC,而不必担心多个编译线程同时修剪.
对并行构建,我建议在构建过程结束时使用ldc-prune-cache,而不是简单地添加,根据是否修剪间隔已过去,在编译完第一个文件缓存修剪的--ir2obj-cache-pruneD编译标志中.

你可能感兴趣的:(dlang,d,d,目标文件,缓存)