Rust 的边界检查是否已经有很大的进步

最近又听到有人说 Rust 做不了高性能程序的原因是内插的边界检查会降低程序运行速度,我想这么多年了应该 Rust 开发团队不会不知道这个问题,因此做了个简单的实验来测试一下是不是这方面已经有了长足的进步

源码

我们有如下代码,该代码为N 皇后问题的算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::time::{SystemTime, UNIX_EPOCH};

const N: i32 = 13;

fn clock_realtime() -> i64 {
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
since_the_epoch.as_millis() as i64
}

fn array_check(array: &[i32], row: i32) -> bool {
if row == 0 {
true
} else {
let x0 = array[row as usize];
for y in 0..row {
let x = array[y as usize];
if x == x0 {
return false;
} else if x - x0 == row - y {
return false;
} else if x0 - x == row - y {
return false;
}
}
true
}
}

fn queen() -> i32 {
let mut array = [0; N as usize];
let mut found = 0;
let mut row = 0;
let mut done = false;
while !done {
if array_check(&array, row) {
if row == N - 1 {
found += 1;
} else {
row += 1;
array[row as usize] = 0;
continue;
}
}
array[row as usize] += 1;
while array[row as usize] >= N {
row -= 1;
if row >= 0 {
array[row as usize] += 1;
} else {
done = true;
break;
}
}
}
found
}

fn main() {
queen();
let ts = clock_realtime();
let found = queen();
let dt = clock_realtime() - ts;
println!("found={} time={} ms", found, dt);
}

我们需要查看汇编,看看 panic 相关的汇编是不是变少

从汇编角度分析

在 Rust 1.88 得到的涉及到边界检查的汇编如下

1
2
3
4
.LBB6_40:
leaq .Lanon.577bbe129332a5e2b73bb2ccd2cfb5e2.7(%rip), %rdx
movl $13, %esi
callq *_ZN4core9panicking18panic_bounds_check17hda0827d94e974e71E@GOTPCREL(%rip)

在 Rust 1.42 得到的涉及到边界检查的汇编如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.LBB4_19:
.cfi_def_cfa_offset 64
leaq .L__unnamed_2(%rip), %rdi
movl $13, %esi
movl $13, %edx
callq *_ZN4core9panicking18panic_bounds_check17h09b793daa6d169ffE@GOTPCREL(%rip)
ud2
.LBB4_25:
leaq .L__unnamed_3(%rip), %rdi
movl $13, %edx
callq *_ZN4core9panicking18panic_bounds_check17h09b793daa6d169ffE@GOTPCREL(%rip)
ud2
.LBB4_17:
leaq .L__unnamed_4(%rip), %rdi
movl $13, %edx
callq *_ZN4core9panicking18panic_bounds_check17h09b793daa6d169ffE@GOTPCREL(%rip)
ud2
.LBB4_15:
leaq .L__unnamed_5(%rip), %rdi
movl $13, %edx
callq *_ZN4core9panicking18panic_bounds_check17h09b793daa6d169ffE@GOTPCREL(%rip)
ud2
.LBB4_9:
leaq .L__unnamed_6(%rip), %rdi
movl $13, %edx
callq *_ZN4core9panicking18panic_bounds_check17h09b793daa6d169ffE@GOTPCREL(%rip)
ud2

可以看到很明显是从五个减少到了一个,说明 Rust 本身也在不断进步

附录

完整的 1.88.0 编译汇编

完整的 1.42.0 编译汇编


Rust 的边界检查是否已经有很大的进步
https://blog.krysztal.dev/2025/07/08/Rust-的边界检查是否已经有很大的进步/
作者
Krysztal
发布于
2025年7月8日
许可协议