我正在初始化一个数组,然后多次反转以查看性能。
我想了解我是否编写了无法比较的代码,或者Rust真的很糟糕以至于花费了很多时间?
以下是Rust的构建和计时过程:
rustc main.rs
time ./main
这会继续运行。真令人惊讶
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);
}
}
Go代码完全可以完成Rust代码在上面的工作。需要注意的重要一点是Go具有垃圾收集功能,而Rust则没有。令人惊讶的是,Go在不到6秒的时间内完成了工作:
go build main.go
time ./main 100000 100000
real 0m5.932s
user 0m5.928s
sys 0m0.004s
package main
import (
"os"
"strconv"
)
func reverse(mylist []int) []int {
length := len(mylist)
half := int(length / 2)
for i := 0; i < half; i++ {
mylist[i], mylist[length-i-1] = mylist[length-i-1], mylist[i]
}
return mylist
}
func main() {
array_size, _ := strconv.Atoi(os.Args[1])
iterations, _ := strconv.Atoi(os.Args[2])
mylist := make([]int, array_size)
for i := 0; i < iterations; i++ {
reverse(mylist)
}
}
答案 0 :(得分:5)
默认情况下,version: "3"
services:
h2o-start:
image: milanpanic2/h2o-start
build:
context: ./h2o-start
ports:
- "54321:54321"
- "54322:54322"
volumes:
- "home/data"
model-generator:
image: milanpanic2/model-generator
build:
context: ./model-generator
ports:
- "8080:8080"
depends_on:
- "h2o-start"
volumes:
- "csvdata:/var/my-data"
volumes:
csvdata:
(和rustc
)在调试模式下编译。它被认为是最有用的默认值,因为它是开发过程中最常编译的一个。
调试模式(尤其是在您的代码中)包括很多检查:每次对cargo
的访问都受到边界检查的保护。
相反,出于基准测试的目的,您希望进行优化编译。如果直接使用mylist[..]
,这就像传递rustc
标志一样简单。
如@ljerdz所述,有一种[T]::reverse
方法,它比您的实现效率更高,因为它在内部使用-O
来进行边界检查。
在操场上快速查看并不会发现您的unsafe
和reverse
之间有什么奇异的区别;优化器已经足够聪明,可以取消边界检查。
不幸的是,它不够智能以消除循环,可能是因为它没有意识到Vec::reverse
和__rust_alloc_zeroed
是内存分配/释放例程,并且没有明显的副作用。