我是Rust的新手,最近一直在研究它。我对比了在Rust和C中通过索引访问数组的性能。
我写了这两个程序:
fn main() {
let mut arr: [[i32; 1000]; 1000] = [[0; 1000]; 1000];
for t in 0..1000 {
for i in 0..1000 {
for j in 0..1000 {
arr[i][j] = (i * j) as i32;
}
}
}
}
在 C 语言中:
#include <stdlib.h>
#include <string.h>
#define ARRSIZE 1000
int main() {
int ** arr = malloc(sizeof(int*) * ARRSIZE);
int i, j, t;
for (i = 0; i < ARRSIZE; ++i) {
arr[i] = malloc(sizeof(int) * ARRSIZE);
memset((void*) arr[i], 0, sizeof(int) * ARRSIZE);
}
for (t = 0; t < ARRSIZE; ++t) {
for (i = 0; i < ARRSIZE; ++i) {
for (j = 0; j < ARRSIZE; ++j) {
arr[i][j] = i * j;
}
}
}
for (i = 0; i < ARRSIZE; ++i) {
free(arr[i]);
}
free(arr);
}
这个想法是创建一个1000x1000的二维数组,并在每次迭代中对每个元素进行简单的算术运算,共进行1000次迭代。
两者之间的性能差距很大(C版本需要近3秒,Rust版本需要45秒)。这正常吗?还是我在Rust版本中做错了什么?
编辑:我尝试禁用边界检查,结果相同。
谢谢。
i
和j
的循环控制,但不改变循环内部的表达式会发生什么?这对Rust的性能有影响吗? - Jonathan Leffler0..1000
表达式如何处理?如果它没有被优化掉,并且每次迭代(和子迭代)都会实际构建某种范围对象,则可能会出现问题。 - Okarustc
的优化级别3(使用-C opt-level=3
)启动程序,它将立即执行完毕。你在性能分析中启用了哪些优化?另外,你的两种代码并不相同。在Rust版本中,你在栈上使用了一个数组。而在C版本中,你使用了堆。这可能对Rust更有利,但我想指出的是,你并没有真正比较相同的情况。 - Cornstalks