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

标签 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

Idiomatic

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

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

With hacks

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

Go

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

Java

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

最佳答案

运行 compiler filename 实际上仍然运行链接器并且可能将大量标准库复制到生成的可执行文件中(特别是伤害 D 和 Go,它们默认静态链接它们的语言运行时以获得更好的效果兼容性)。

给定这个微不足道的 D hello world:

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 库可以消除这种情况,并提供更加统一的外观。

  • 但是,使用标准库对于查看可扩展性很重要。

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

不过,为大型构建等待几分钟 是个问题。如果我们可以将时间缩短到几秒钟,那就是一个重大胜利。

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

因此,D 构建标准库所花费的时间令人印象深刻。比 C hello world 慢(因为 C 编译器对较小的 lib 做的工作更少),但是你已经看到了 C++ hello world 的好处,它每行速度更慢,并且在每次构建时往往有更多的工作要做(解析#includes 等)。

一个好的编译器基准测试应该比小程序更能隔离这些问题并测试可伸缩性。尽管如果您正确运行测试以确保公平比较,D 在小程序上也做得非常

关于c - 为什么 C 比 Go 或 D 更快地构建小程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36066447/

相关文章:

c - 将变量传递给 pthread_create 函数

r - R中学生化外部残差的快速准确计算

java - 在 Jboss 中使用大页面

iphone - AutoLayout 的 UITableViewCell 性能不佳

go - 这个函数在哪里返回非错误?

go找不到sdl

go - 并行执行 DynamoDB 查询(全局二级索引的 BatchGetItems)

c++ - .h 文件的意义是什么?

C - 反向递归链表 : why use double pointer?

c++ - "-x c"后返回 native 文件处理