不同编程语言的执行效率竟然差这么多!

498 阅读3分钟

博客首发于:www.weeco.tech/3d24fbc2337…

为什么做这个实验

近期在公司的一个项目中惊叹于Bash脚本转换为C/C++程序后,再编译生成二进制文件的效率提升比例,突然就有个想法,对比一下不同语言的执行效率呢? 我们就选取最为常见C、C++、Python2、Python3、Go进行对比,看看同样的内容,不同的语言执行效率有多大的差异。 我们这边通过不同编程语言计算100W以内的质数这样一个功能,进行执行效率对比。

实验环境介绍

虚拟机:host-CPU直通 Linux CentOS 7.6 CPU:Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz gcc版本:4.8.5-44 g++版本:4.8.5-44 go版本:1.18.9 Python2版本:2.7.5 Python3版本:3.6.8

源代码及编译指令

如下分别是C、C++、Go、Python3、Python2代码,其中C、C++、Go代码均编译为二进制文件。 编译指令分别为: C:gcc prime_number.c -O3 -o prime_number_c -lm -std=c99 C++:g++ prime_number.cpp -O3 -o prime_number_cpp -lm Go:go build -o prime_number_go prime_number.go

#include <stdio.h>
#include <stdbool.h>
#include <math.h>

bool is_prime(int n) {
    if (n < 2) {
        return false;
    }
    for (int i = 2; i <= sqrt(n); i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    for (int i = 2; i < 1000000; i++) {
        if (is_prime(i)) {
            printf("%d\n", i);
        }
    }
    return 0;
}
#include <iostream>
#include <cmath>

using namespace std;

bool is_prime(int n) {
    if (n < 2) {
        return false;
    }
    for (int i = 2; i <= sqrt(n); i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    for (int i = 2; i < 1000000; i++) {
        if (is_prime(i)) {
            cout << i << endl;
        }
    }
    return 0;
}
package main

import (
    "fmt"
    "math"
)

func isPrime(n int) bool {
    if n < 2 {
        return false
    }
    for i := 2; i <= int(math.Sqrt(float64(n))); i++ {
        if n%i == 0 {
            return false
        }
    }
    return true
}

func main() {
    for i := 2; i < 1000000; i++ {
        if isPrime(i) {
            fmt.Println(i)
        }
    }
}
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

for i in range(2, 1000000):
    if is_prime(i):
        print(i)
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

for i in range(2, 1000000):
    if is_prime(i):
        print i
对比方式

通过/bin/time -vvv [command] > [file],同时对比C/C++/Go语言编译生成的二进制文件,Python2/3输出的结果是否一致,以及不同语言执行所需的时间。

/bin/time -vvv ./prime_number_c > /tmp/prime_number_c.log
/bin/time -vvv ./prime_number_cpp > /tmp/prime_number_cpp.log
/bin/time -vvv ./prime_number_go > /tmp/prime_number_go.log
/bin/time -vvv python2 prime_number_py2.py > /tmp/prime_number_py2.log
/bin/time -vvv python2 prime_number_py3.py > /tmp/prime_number_py3.log
对比结果

通过以上5条指令,得到5种编程语言的执行结果,通过计算各结果的MD5值,可知其结果一致。

c13929ee9d2aea8f83aa076236079e94  prime_number_c.log
c13929ee9d2aea8f83aa076236079e94  prime_number_cpp.log
c13929ee9d2aea8f83aa076236079e94  prime_number_go.log
c13929ee9d2aea8f83aa076236079e94  prime_number_py2.log
c13929ee9d2aea8f83aa076236079e94  prime_number_py3.log

以User time和System Time总和,即最终的墙上时间作为执行时间进行对比,各编程语言执行时间分别为:

  • C:0.16+0.00=0.16秒
  • C++:0.15+0.02=0.17秒
  • Go:0.50+0.01=0.51秒
  • Python2:5.62+0.00=5.62秒
  • Python3:5.57+0.01=5.58秒

根据各编程语言的执行时间,绘制了一张图,能够更明显地看出各语言的性能差异:

不同编程语言的执行效率对比.png

结论

从数据可以很明显看出,Python2/3的执行时间时间远远高于其他三者,大约是C/C++执行时间的35倍;C/C++的执行时间在误差允许范围内可认为是一致的。同样是编译成二进制,Go编译出来的二进制文件,其执行效率约为C/C++的1/3,当然可能与其编译参数有关。

我们能做什么

既然我们知道这三者的性能差异,那么在对性能有要求的场景下,我们应该尽可能选用C/C++编写,其次选择Go语言。 如果系统整体是用Python完成的,对于其中的高频调用子函数,可以考虑将其转换为C/C++或者Go语言,然后通过二进制调用的方式合入系统中。

这个实验还有后续吗

在这个实验当中,我们对比了不同编程语言C/C++/Go/Python2/Python3的执行效率,很明显,Python2和Python3的效率远低于其他几者,那么是否存在一些优化手段、优化工具,能够提升Python代码的执行效率呢? 留个悬念,下个博客见~