C被公认为速度最快的编程语言,Rust的速度接近于C,二者差距在毫厘之间。如果单纯和C/Rust比速度的话,Python处于被碾压的地位,差不多慢了一个量级。不过,下面这个测试,却呈现了一个颠覆性的结果:使用相同的算法,分别用C语言、Rust语言和Python语言编程计算1亿以内素数的个数,三者用时之比为1:0.96:1.15
!Rust居然比C快了一丢丢,而Python也不像是传说中的那么不堪,只比C慢了半个身位。差距是如此之小,三大语言几乎打了个平手。
测试任务 | C平均耗时 | Rust平均耗时 | Python |
---|---|---|---|
计算1亿以内素数的个数 | 467.88毫秒 | 447.80毫秒 | 536.30毫秒 |
以下附上本次测试的C/Rust/Python代码,以便对该测试感兴趣的同学验证结论。我深知在这里讨论不同语言的性能是一个危险话题,故声明在先:本文无意褒贬任何一门编程语言,欢迎针对测试代码提出改进意见,若有非技术性意见,请免开尊口。
C代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int prime_sieve(int n) {
int m = (int)sqrt((float)n) + 1;
int total = 0;
char *arr = (char *)malloc(n * sizeof(char));
for (int i = 0; i < n; i++) {
arr[i] = 1;
}
for (int i = 2; i < m; i++) {
if (arr[i] > 0) {
int j = 2 * i;
while (j < n) {
arr[j] = 0;
j += i;
}
}
}
for (int i = 2; i < n; i++) {
if (arr[i] > 0) {
total += 1;
}
}
return total;
}
int main() {
clock_t start, finish;
double duration;
double time_sum = 0.0;
for (int i = 0; i < 10; i++) {
start = clock();
int total = prime_sieve(100000000);
finish = clock();
duration = (double)(finish - start) * 1000.0 / CLOCKS_PER_SEC;
time_sum += duration;
printf("%d. 1亿以内的自然数中素数有%d个,耗时%f毫秒\n", i, total, duration);
}
printf("--------------------------------------------------\n");
printf("C最终成绩:运行10次,平均耗时%f毫秒\n", time_sum/10.0);
return 0;
}
编译开启O3优化,运行结果如下。
xufive@xuxiangwudeMacBook-Pro prime % gcc sieve.c -O3 -o sieve
xufive@xuxiangwudeMacBook-Pro prime % ./sieve
0. 1亿以内的自然数中素数有5761455个,耗时483.101000毫秒
1. 1亿以内的自然数中素数有5761455个,耗时467.608000毫秒
2. 1亿以内的自然数中素数有5761455个,耗时468.347000毫秒
3. 1亿以内的自然数中素数有5761455个,耗时467.092000毫秒
4. 1亿以内的自然数中素数有5761455个,耗时464.485000毫秒
5. 1亿以内的自然数中素数有5761455个,耗时455.552000毫秒
6. 1亿以内的自然数中素数有5761455个,耗时468.371000毫秒
7. 1亿以内的自然数中素数有5761455个,耗时466.685000毫秒
8. 1亿以内的自然数中素数有5761455个,耗时468.269000毫秒
9. 1亿以内的自然数中素数有5761455个,耗时469.323000毫秒
--------------------------------------------------
C最终成绩:运行10次,平均耗时467.883300毫秒
Rust代码
use std::time::Instant;
fn main() {
let mut time_sum: u128 = 0;
for i in 0..10 {
let now = Instant::now();
let total = prime_sieve(100_000_000);
let duration = now.elapsed().as_millis();
time_sum += duration;
println!("{}. 1亿以内的自然数中素数有{}个,耗时{}毫秒", i, total, duration);
}
println!("--------------------------------------------------");
println!("Rust最终成绩:运行10次,平均耗时{}毫秒", (time_sum as f64)/10.0);
}
fn prime_sieve(n: usize) -> usize {
let m: usize = f64::sqrt(n as f64) as usize + 1;
let mut total: usize = 0;
let mut arr: Vec<u8> = [1].repeat(n);
for i in 2..m {
if arr[i] > 0 {
let mut j: usize = 2 * i;
while j < n {
arr[j] = 0;
j += i;
}
}
}
for i in 2..n {
if arr[i] > 0 {
total += 1;
}
}
total
}
构建使用release参数,运行结果如下。
xufive@xuxiangwudeMacBook-Pro prime % cargo build --release
Finished release [optimized] target(s) in 0.00s
xufive@xuxiangwudeMacBook-Pro prime % cd target/release
xufive@xuxiangwudeMacBook-Pro release % ./prime
0. 1亿以内的自然数中素数有5761455个,耗时430毫秒
1. 1亿以内的自然数中素数有5761455个,耗时448毫秒
2. 1亿以内的自然数中素数有5761455个,耗时452毫秒
3. 1亿以内的自然数中素数有5761455个,耗时447毫秒
4. 1亿以内的自然数中素数有5761455个,耗时449毫秒
5. 1亿以内的自然数中素数有5761455个,耗时453毫秒
6. 1亿以内的自然数中素数有5761455个,耗时447毫秒
7. 1亿以内的自然数中素数有5761455个,耗时449毫秒
8. 1亿以内的自然数中素数有5761455个,耗时451毫秒
9. 1亿以内的自然数中素数有5761455个,耗时452毫秒
--------------------------------------------------
Rust最终成绩:运行10次,平均耗时447.8毫秒
Python代码
import time
import numpy as np
def get_prime_num(n):
"""返回小于n的自然数中素数的个数"""
m = int(np.sqrt(n)) + 1
arr = np.ones(n, dtype=np.uint8)
total = 0
for i in range(2, m):
if arr[i] > 0:
arr[2*i::i] = 0
return np.where(arr[2:] > 0)[0].shape[0]
if __name__ == '__main__':
time_sum = 0
for i in range(10):
t0 = time.time()
total = get_prime_num(100_000_000)
dutation = round((time.time() - t0) * 1000)
time_sum += dutation
print('%d. 1亿以内的自然数中素数有%d个,耗时%d毫秒'%(i, total, dutation))
print("--------------------------------------------------")
print("Python最终成绩:运行10次,平均耗时%.3f毫秒" % (time_sum/10.0));
我的Python解释器版本为py3.11.2,运行结果如下。
xufive@xuxiangwudeMacBook-Pro prime % python3 prime.py
0. 1亿以内的自然数中素数有5761455个,耗时526毫秒
1. 1亿以内的自然数中素数有5761455个,耗时540毫秒
2. 1亿以内的自然数中素数有5761455个,耗时538毫秒
3. 1亿以内的自然数中素数有5761455个,耗时538毫秒
4. 1亿以内的自然数中素数有5761455个,耗时538毫秒
5. 1亿以内的自然数中素数有5761455个,耗时538毫秒
6. 1亿以内的自然数中素数有5761455个,耗时537毫秒
7. 1亿以内的自然数中素数有5761455个,耗时537毫秒
8. 1亿以内的自然数中素数有5761455个,耗时535毫秒
9. 1亿以内的自然数中素数有5761455个,耗时536毫秒
--------------------------------------------------
Python最终成绩:运行10次,平均耗时536.300毫秒