作为练习,我正在尝试微优化 Rust 1.3.0 中的代码。我在数组上有一个循环。像这样:
loop {
for i in 0..arr.len() {
// something happens here
}
}
由于数组在 Rust 中是固定大小的,编译器会通过仅评估一次 arr.len()
并重用该值来优化代码,还是会在顶部的每次传递中评估表达式级循环?除了 arr.len()
之外,这个问题可以扩展到没有副作用的更多计算量大的函数。
换句话说,上面的代码是否等同于:
let arr_len = arr.len();
loop {
for i in 0..arr_len {
// something happens here
}
}
最佳答案
..
是一个范围运算符,它形成一个 Range<Idx>
对象(或衍生物: RangeFrom
, RangeFull
或 RangeTo
)。这些对象只包含索引(Idx
类型),因此您可以放心 .len()
只计算一次。
一般来说,检查 LLVM IR 是个好主意。如果你有一个综合示例,你可以很容易地使用 playground。对于 example :
// A black-box prevents optimization, and its calls are easy to spot.
extern {
fn doit(i: i32) -> ();
}
fn main() {
let arr = [1, 2, 3, 4, 5];
for i in 0..arr.len() {
unsafe { doit(arr[i]); }
}
}
产生以下功能:
; Function Attrs: uwtable
define internal void @_ZN4main20hd87dea49c835fe43laaE() unnamed_addr #1 {
entry-block:
tail call void @doit(i32 1)
tail call void @doit(i32 2)
tail call void @doit(i32 3)
tail call void @doit(i32 4)
tail call void @doit(i32 5)
ret void
}
在这种情况下,对于固定长度,根本没有循环:它已被展开。
关于optimization - Rust 会优化计算范围内的循环吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33109882/