Go vs Swift vs C++ 简单微型基准比较测试

红薯 发布于 2016/02/22 11:14
阅读 5K+
收藏 0

我之前阅读过一篇比较的文章 Swift vs Go vs Python battle,但觉得时间太老了,这是在一年前写的,某种意义上说,一年时间太长了。

因此我决定在我的 Mac 笔记本 (1.7 GHz Intel Core i5) 上重新做这个测试,同时增加了 C++ 的测试。使用 Python 脚本可以很方便的重新测试(Python 比编译型语言要慢 10 倍左右),而对 C++ 是比较公平的。这次测试的版本是:Go 1.5.3, Swift 2.1.1, C++ clang-700.1.81.

我没法确保我的测试时严谨的,micro-benchmarking 也不关心语言本身的生态、工具和可维护性等方面。同时也不会太关注性能。但 micro-benchmarking 就这样。

下面是这几个语言的测试代码:

Go

package main
import "fmt"

func main() {
    var sum int64 = 0

    for e := 0; e < 200; e++ {
        sum = 0

        var x[]int64
        for i := 0 ; i < 1000000; i++ {
            x = append(x, int64(i));
        }

        var y[]int64
        for i := 0 ; i < 1000000-1; i++ {
            y = append(y, x[i]+x[i+1]);
        }

        for i := 0 ; i < 1000000; i += 100 {
            sum += y[i];
        }
    
    }
    
    fmt.Println(sum);
}

Swift

var sum : Int64 = 0

for e in 0..<200 {
    sum = 0 
    
    var x : [Int64] = []
    for (var i = 0; i < 1000000; i++) {
        x.append(Int64(i));
    }
        
    var y: [Int64] = []
    for (var i = 0; i < 1000000-1; i++) {
        y.append(x[i] + x[i+1]);
    }
        
    for (var i = 0; i < 1000000; i+=100) {
        sum += y[i]
    }   
}
        
print(sum)

C++

#include <vector>
#include <iostream>

int main() {
    int64_t sum = 0;

    for(int e = 0; e < 200; e++) {
        sum = 0;

        std::vector<int64_t> x;
        for(int i = 0; i < 1000000; i++) {
            x.push_back(i);
        }

        std::vector<int64_t> y;
        for(int i = 0; i < 1000000-1; i++) {
            y.push_back(x[i] + x[i+1]);
        }

        for (int i = 0; i < 1000000; i += 100) {
            sum += y[i];
        }
    }

    std::cout << sum << std::endl;
}

为什么我会使用 int64 来代替 int 呢?在我的 64 位系统中 C++ 的 int 是 32 位的,而 Go 和 Swift 默认是 64 位的,为了公平起见。


好了,接下来战斗开始:
go build -o test-go go/test.go
swiftc -O -o test-swift swift/test.swift
c++ -O3 -o test-c cplusplus/test.cc
GOMAXPROCS=2 time ./test-go
9999010000 4.32 real 5.99 user         0.38 sys
GOMAXPROCS=1 time ./test-go
9999010000 3.93 real 3.89 user         0.05 sys
time ./test-swift
9999010000 3.96 real 2.82 user         1.12 sys
time ./test-c
9999010000 2.37 real 1.74 user         0.62 sys

从这个测试结果中我们能看到什么?对于 Go 语言来说 GOMAXPROCS 增加了测量的开销。正如我们所期望的,这个影响并不大。C++ 还是如预期般的快。事实上,这个性能的差异体现在内存分配和垃圾收集上。

但让我们来试试一个更小的数组,避免内存的分配影响太大。下面的测试条件 e<=2000 (而不是 200) 并且循环迭代次数使用 100k 替换之前的 1m:

go build -o test-go go/test.go
swiftc -O -o test-swift swift/test.swift
c++ -O3 -o test-c cplusplus/test.cc
GOMAXPROCS=2 time ./test-go
99901000 4.40 real 5.65 user         1.10 sys
GOMAXPROCS=1 time ./test-go
99901000 5.06 real 5.07 user         0.83 sys
time ./test-swift
99901000 2.32 real 2.29 user         0.01 sys
time ./test-c
99901000 1.39 real 1.37 user         0.01 sys


现在我们看到了 Go 落后了,可能是因为其依赖于自己的代码生成器。居然比 C 要慢 3 倍之多。而 Swift 使用 LLVM,代码生成器和 C++ 一样。但增加了一些检查和垃圾收集,因此 Swift 性能比 C++ 慢 2 倍。

从这个测试结果中我们能知道什么?

我怀疑如果 Swift 有首类并发支持,那么很多人会选择 Swift 而不是 Go。但我们不能既要求速度又要好的维护性,如果你不在意并发上慢一点点的话,那就选择 Swift。

此外我还有 Erlang,但其基准测试似乎不太适合这个场景。

英文原文 lionet.livejournal 翻译有点拙劣,凑合看!

加载中
1
little_kid
little_kid

C++ 用法不对哦楼主

#include <vector>
#include <iostream>
 
intmain() {
    int64_t sum = 0;
 
    for(inte = 0; e < 200; e++) {
        sum = 0;
 

        std::vector<int64_t> x;

        x.resize(1000000);

        for(inti = 0; i < 1000000; i++) {
            x.push_back(i);
        }
 

        std::vector<int64_t> y;

        y.resize(1000000);

        for(inti = 0; i < 1000000-1; i++) {
            y.push_back(x[i] + x[i+1]);
        }
 
        for(inti = 0; i < 1000000; i += 100) {
            sum += y[i];
        }
    }
 
    std::cout << sum << std::endl;

}


楼主再试一下,速度会更快;

另外对于这大量的apend操作建议使用std::list<int64_t>

little_kid
little_kid
回复 @胡人2 : en..习惯上一直用的是resize,差别是resize之后支持operator []。此处用的是push_back应该用reserve,感谢提醒。 原文是翻译的,不是楼主写的
胡人2
不是resize,是reserve btw,看上去楼主根本不熟悉c++,不熟就别丢人现眼。
0
c
czy463
go这么测试并不公平吧
0
lunny
lunny

var x = make([]int64, 0, 1000000)

var y = make([]int64, 0, 1000000)

Go的代码改下这个

0
Storm-Cai
Storm-Cai
专注方向不一样。 测试能说明一些问题, 但是不能作为一个教科书一样的基本准则。go   swift  c专注方向不一样。 但是要我选择一门最喜欢的语言, 我会回答说是swift。
0
景愿
景愿

红薯已经很久没有认真的发一篇东西了,赞一个,

相对于swift来说,这一年确实很久了

0
宏哥
宏哥

swift不错, 而且有应用场景, 可以在IOS上做APP开发。

并发其实不是语言层面的东西, GO和ERLang的并发不是很好的方向

0
OSC首席键客
OSC首席键客
英文翻译的文章!
0
s
sw55555
如果C++用数组速度会怎样?
東條・スペンサー・咲
東條・スペンサー・咲
估计计算倍数的时候数太大不好算采用的vector吧 :)
返回顶部
顶部