HeadlinesBriefing favicon HeadlinesBriefing.com

匹配拼图块件与令人失望的基准

Hacker News •
×

匹配拼图块件件与令人失望的基准2026年3月20日我最近有一段代码使用.to_lowercase()来排序一些文本。这需要一点内存。顺便一提,代码使用.sort_by_cached_key,这相当酷。但我 wondered whether做 .to_lowercase() log(n)次而不是n次会比为每个条目分配一个String更慢,鉴于对于许多字符串,即使是前几个字符也是不同的。首先,在Rust中无条件地比较两个&strs是可能的,如果有点麻烦。这里的解决方案是遍历所有字符,然后调用char::to_lowercase,这会返回另一个字符迭代器(因为某些字符可以对应多个小写字符),我们可以flat_map。第二个拼图块件是,Iterator有一个cmp方法,但不实现Ord,因为它不是幂等的:如果你调用cmp,你会耗尽迭代器。仍然可以通过sort_by,我们可以在小写转换和比较之间交叉进行。姑且说,我还添加了unicase crate到基准测试中。作为好奇心旺盛的人,我自然写了一个benchmark,这段代码足够短,这里可以重现(如果你对结论不感兴趣,向下滚动):use fake::faker::name::raw:: Name;use fake::{locales:: EN, Fake};fn setup(num: usize) -> Vec<String> {(0..num).map(|_| Name(EN).fake()).collect::<Vec<String>>()}#[divan::bench(args = [1, 5, 10, 100, 1000, 10000])]fn sort_by_cached_lowercase(bencher: divan:: Bencher, size: usize) {let names = setup(size);bencher.counter(size).bench_local(|| {let mut sorted = names.clone();sorted.sort_by_cached_key(|name| name.to_lowercase());sorted})}#[divan::bench(args = [1, 5, 10, 100, 1000, 10000])]fn sort_by_iter_lowercase(bencher: divan:: Bencher, size: usize) {let names = setup(size);bencher.counter(size).bench_local(|| {let mut sorted = names.clone();fn caseless(s: &String) -> impl Iterator<Item = char> + '_ {s.chars().flat_map(char::to_lowercase)}sorted.sort_by(|s1, s2| caseless(s1).cmp(caseless(s2)));sorted})}#[divan::bench(args = [1, 5, 10, 100, 1000, 10000])]fn sort_by_unicase(bencher: divan:: Bencher, size: usize) {let names = setup(size);bencher.counter(size).bench_local(|| {let mut sorted = names.clone();sorted.sort_by(|s1, s2| unicase:: Uni Case::new(s1).cmp(&unicase:: Uni Case::new(s2)));sorted})}fn main() {// 运行已注册的基准.divan::main();}该结果在我的M2-MAX Mac Book Pro上:计时器精度:41 nslow fastest │ slowest │ median │ mean │ samples │ iters├─ sort_by_cached_lowercase │ │ │ │ ││ ├─ 1 16.68 ns │ 18.14 ns │ 17.49 ns │ 17.49 ns │ 100 │ 25600│ │ 59.94 Mitem/s │ 55.1 Mitem/s │ 57.15 Mitem/s │ 57.15 Mitem/s │ ││ ├─ 5 212.9 ns │ 265 ns │ 215.5 ns │ 219.2 ns │ 100 │ 3200│ │ 23.47 Mitem/s │ 18.86 Mitem/s │ 23.19 Mitem/s │ 22.8 Mitem/s │ ││ ├─ 10 452.5 ns │ 567.1 ns │ 457.7 ns │ 462.2 ns │ 100 │ 1600│ │ 22.09 Mitem/s │ 17.63 Mitem/s │ 21.84 Mitem/s │ 21.63 Mitem/s │ ││ ├─ 100 5.207 µs │ 11.33 µs │ 5.291 µs │ 5.455 µs │ 100 │ 100│ │ 19.2 Mitem/s │ 8.824 Mitem/s │ 18.89 Mitem/s │ 18.32 Mitem/s │ ││ ├─ 1000 73.62 µs │ 110.9 µs │ 75.99 µs │ 78.89 µs │ 100 │ 100│ │ 13.58 Mitem/s │ 9.009 Mitem/s │ 13.15 Mitem/s │ 12.67 Mitem/s │ │⎯ 10000 853.7 µs │ 1.053 ms │ 864.8 µs │ 886.3 µs │ 100 │ 100│ 11.71 Mitem/s │ 9.495 Mitem/s │ 11.56 Mitem/s │ 11.28 Mitem/s │ ├─ sort_by_iter_lowercase │ │ │ │ ││ ├─ 1 13.91 ns │ 23.35 ns │ 14.89 ns │ 15.68 ns │ 100 │ 25600│ │ 71.87 Mitem/s │ 42.81 Mitem/s │ 67.15 Mitem/s │ 63.76 Mitem/s │ ││ ├─ 5 134.8 ns │ 196 ns │ 137.4 ns │ 148.6 ns │ 100 │ 3200│ │ 37.08 Mitem/s │ 25.5 Mitem/s │ 36.37 Mitem/s │ 33.64 Mitem/s │ ││ ├─ 10 442.1 ns │ 1.03 µs │ 483.8 ns │ 519.1 ns │ 100 │ 800│ │ 22.61 Mitem/s │ 9.702 Mitem/s │ 20.66 Mitem/s │ 19.26 Mitem/s │ ││ ├─ 100 17.33 µs │ 34.12 µs │ 18.16 µs │ 19.66 µs │ 100 │ 100│ │ 5.769 Mitem/s │ 2.93 Mitem/s │ 5.504 Mitem/s │ 5.086 Mitem/s │ ││ ├─ 1000 337.6 µs │ 433 µs │ 352.1 µs │ 355.4 µs │ 100 │ 100│ │ 2.961 Mitem/s │ 2.309 Mitem/s │ 2...