为什么C比Go或D更快地构建小程序?

时间:2016-03-17 16:30:24

标签: c performance go build d

Go和D广告宣传拥有令人难以置信的快速编译器。 由于语言本身的现代设计,并考虑了并发单通道解析。

了解大部分构建时间浪费在链接阶段。我想知道为什么gcc在小程序上仍然更快。

C

#include <stdio.h>    
int main() {
    printf("Hello\n");
}
$ time gcc hello.c
real    0m0.724s
user    0m0.030s
sys     0m0.046s

d

惯用

import std.stdio;
void main() {
    writeln("Hello\n");
}
$ time dmd hello.d

real    0m1.620s
user    0m0.047s
sys     0m0.015s

黑客攻击

import core.stdc.stdio;
void main() {
    printf("Hello\n");
}
$ time dmd hello.d
real    0m1.593s
user    0m0.061s
sys     0m0.000s

$ time dmd -c hello.d
real    0m1.203s
user    0m0.030s
sys     0m0.031s

开始

package main
import "fmt"
func main() {
    fmt.Println("Hello.")
}
$ time go build hello.go
real    0m2.109s
user    0m0.016s
sys     0m0.031s

爪哇

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello.");
    }
}
$ time javac Hello.java
real    0m1.500s
user    0m0.031s
sys     0m0.031s

1 个答案:

答案 0 :(得分:9)

运行compiler filename实际上仍然运行链接器并且可以将大量标准库复制到生成的可执行文件中(尤其是损坏D和Go,默认情况下它们的语言运行时静态链接以获得更好的兼容性)。 / p>

鉴于这个琐碎的D hello世界:

import std.stdio;
void main() { writeln("hello world"); }

让我告诉你我电脑上的一些时间:

$ time dmd hello.d

real    0m0.204s
user    0m0.177s
sys     0m0.025s

与使用-c跳过链接步骤相比,这意味着“编译,不要链接”:

$ time dmd -c hello.d

real    0m0.054s
user    0m0.048s
sys     0m0.006s

将时间缩短到第一次运行的大约1/4 - 在这个小程序中,将近3/4的编译时间实际上是链接。

现在,让我稍微修改一下程序:

import core.stdc.stdio;
void main() { printf("hello world\n"); }

$ time dmd -c hello.d

real    0m0.017s
user    0m0.015s
sys     0m0.001s

使用printf而不是writeln切成两半!我会回到这个。

而且,为了比较,编译+链接:

$ time dmd hello.d

real    0m0.099s
user    0m0.083s
sys     0m0.014s

这让我们知道发生了什么:

  • 链接器占用了大量时间。使用-c将其从等式中删除。

  • 解析标准库也需要很长时间。仅使用C函数而不是D lib可以将其删除并提供更多苹果到苹果的外观。

  • 但是,使用stdlib对于查看可伸缩性非常重要。

什么D(我认为,Go,但我不太了解它们)的目的是减少编译中型到大型程序的时间。小程序已经很快 - 等待几分之一秒(或者在较慢的计算机上可能只有一两个,我现在在那个计算机上有一个很好的SSD可以加快速度,在旋转硬盘上运行相同的命令磁盘约占时间的两倍!)对于小型构建来说并不是什么大问题。

等待几个分钟进行大型构建是一个问题。如果我们可以将其减少到几秒钟,那将是一场重大胜利。

编译100,000行的时间比编译10的时间更重要。因此初始化时间并不重要。链接时间很重要,但编译器本身没有做太多(链接器是由不同的团队编写的单独程序,尽管在其他地方也有努力改进它)。

因此,构建包括标准库在内的时间是令人印象深刻的。比C hello世界慢(因为C编译器对较小的lib的工作量较少),但是你已经看到了比C ++ hello世界更好的优点,每行更慢,而且每次构建都需要做更多的工作(解析) #includes等。)

良好的编译器基准测试希望将这些问题与测试可扩展性相比较,而不是小程序。虽然如果你运行测试权以确保公平比较,D对小程序也非常非常