大佬 我想问下 ,match 和 hash map 哪个好呢?match 会有性能问题吗
来源:1-2 课程导学

emoPokey
2023-09-14
大佬 我想问下 ,match 和 hash map 哪个好呢?match 会有性能问题吗
对这个match 理解不深,感觉没有 switch 好用啊,但是 switch是有性能问题的
1回答
-
叶枭
2023-09-22
Rust 官方的态度是对于非稀疏的 match…case, 编译器可以将相关代码优化为查表, 也就是 O(1) 复杂度. 但是事实是, 如果你真的去编写一个巨大的 match...case 再用 objdump 去检查它编译出来的汇编代码, 会发现它底层"可能"是巨大的 if…else if…else 结构. 这样执行一次 match 的时间, 是要与 case 数成正比的. 注意: 优化到查表是编译器优化的一部分, 编译器能不能帮你优化你在写代码的时候是不知道的, 所以我用的是"可能".
还有另一点, 使用巨大的 match...case 语句, 可能会导致栈空间过大而 stack overflow, 例如你在 case 下定义变量, 那么每个 case 下变量使用的栈空间会被提前分配好, 即使你未进入对应的 case 分支.
从经验来说, 如果 case 数目小于几十条, 那么用 match 或者 array/hashmap 查表等都不会有太大的问题; 一旦接近 100 条, 最好是采用 array 查表法.
我写了一个测试文件, 您可以自己跑一下查看效果
```rs
use std::ops::{Add, Div, Mul, Sub};
fn add<T>(a: T, b: T) -> T
where
T: Add<Output = T>,
{
a + b
}
fn sub<T>(a: T, b: T) -> T
where
T: Sub<Output = T>,
{
a - b
}
fn mul<T>(a: T, b: T) -> T
where
T: Mul<Output = T>,
{
a * b
}
fn div<T>(a: T, b: T) -> T
where
T: Div<Output = T>,
{
a / b
}
fn calculate_1<T>(a: T, b: T, op: usize) -> T
where
T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T> + Copy,
{
match op {
0 => add(a, b),
1 => sub(a, b),
... // 请自行补齐一下
254 => mul(a, b),
255 => div(a, b),
_ => unreachable!(),
}
}
fn calculate_2<T>(a: T, b: T, op: usize, opList: &[fn(T, T) -> T]) -> T
where
T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T> + Copy,
{
opList[op](a, b)
}
fn main() {
let now = std::time::SystemTime::now();
for i in 0..10000000 {
calculate_1(3, 3, i % 256);
}
println!("{:?}", now.elapsed());
let opList = [
add::<u32>, sub::<u32>, mul::<u32>, div::<u32>, add::<u32>, sub::<u32>, mul::<u32>,
... // 请自行补齐一下
add::<u32>, sub::<u32>, mul::<u32>, div::<u32>,
];
let now = std::time::SystemTime::now();
for i in 0..10000000 {
calculate_2(3, 3, i % 256, &opList);
}
println!("{:?}", now.elapsed());
}
```
10
相似问题