为什么我执行阵列反转的Rust程序要比同等的Go程序慢?

Tah*_*een 0 go rust

我正在初始化一个数组,然后将其反转多次以查看性能。

我想了解我是否编写了无法比较的代码,还是Rust真的很糟糕以至于花费了很多时间?

这是Rust的构建和计时过程:

rustc main.rs
time ./main
Run Code Online (Sandbox Code Playgroud)

这将继续下去。令人惊讶

fn reverse(mylist: &mut Vec<u16>) {
    let length = mylist.len();

    let mid_length = length / 2;

    for number in 0..mid_length {
        let mut a = mylist[number];
        let mut b = mylist[length - number - 1];

        mylist[number] = b;

        mylist[length - number - 1] = a;
    }
}

fn main() {
    let array_size = 100000;

    let iterations = 100000;

    let mut v = vec![0u16; array_size];

    for _ in 0..iterations {
        reverse(&mut v);
    }
}
Run Code Online (Sandbox Code Playgroud)

Go代码完全可以完成Rust代码在上面的工作。需要注意的重要一点是Go具有垃圾收集功能,而Rust则没有。令人惊讶的是,Go在不到6秒的时间内完成了工作:

fn reverse(mylist: &mut Vec<u16>) {
    let length = mylist.len();

    let mid_length = length / 2;

    for number in 0..mid_length {
        let mut a = mylist[number];
        let mut b = mylist[length - number - 1];

        mylist[number] = b;

        mylist[length - number - 1] = a;
    }
}

fn main() {
    let array_size = 100000;

    let iterations = 100000;

    let mut v = vec![0u16; array_size];

    for _ in 0..iterations {
        reverse(&mut v);
    }
}
Run Code Online (Sandbox Code Playgroud)

go build main.go
time ./main 100000 100000

real    0m5.932s
user    0m5.928s
sys 0m0.004s
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 5

默认情况下,rustc(和cargo)在调试模式下编译。它被认为是最有用的默认值,因为它在开发过程中最经常编译。

调试模式,尤其是在代码中,包括许多检查:mylist[..]除其他事项外,每次访问均受边界检查的保护。

相反,出于基准测试目的,您希望进行优化编译。如果rustc直接使用,则就像传递-O标志一样简单。


正如@ljerdz指出的那样,有一种[T]::reverse方法,它比您的实现更有效,因为它在内部用于unsafe取消边界检查。

但是,在操场上快速查看并不会发现您reverseVec::reverse您的情况之间有什么异乎寻常的区别;优化器已经足够聪明,可以取消边界检查。

不幸的是,它不够智能以消除循环,这可能是因为它没有意识到这一点,__rust_alloc_zeroed并且__rust_dealloc是内存分配/释放例程,并且没有明显的副作用。