#hash-map #small-vec #hybrid #memory-map #map #small

hybridmap

使用smallvec和std hashmap实现的混合映射

3个版本

0.1.2 2024年8月1日
0.1.1 2024年1月30日
0.1.0 2024年1月29日

#1039 in 算法

Download history 1/week @ 2024-06-26 13/week @ 2024-07-03 12/week @ 2024-07-24 115/week @ 2024-07-31 2/week @ 2024-08-07

每月129次下载

Apache-2.0

26KB
445

HybridMap

HybridMap是一个Rust™混合映射实现,它使用内存堆栈上的向量来实现小型映射,而在其他情况下使用哈希映射。

与大多数混合技术一样,包括两个组件而不是一个组件是多余的。然而,混合解决方案可以针对特定用例提供一些价值。

对于小型映射,特别是那些存在于内存堆栈上且生命周期较短的映射,HybridMap可能略快一些,通常不超过16个条目,并且查找次数不多。

示例

HybridMap的使用方式与大多数其他映射类似。

use hybridmap::HybridMap;

let mut map = HybridMap::<i32, &str>::new();
map.insert(1, "one");
map.insert(2, "two");

assert_eq!(map.get(&1), Some(&"one"));
assert_eq!(map.len(), 2);

基准测试

基准测试可能无法代表您的用例。如果您创建了多个短暂的小型映射,您可能会看到以下显示的一些收益。您也可能比标准哈希映射的性能更差。

您可以将基准测试适应到您的用例中。如果您不确定是否应该使用这个混合映射还是哈希映射,您应该选择哈希映射。如数字所示,性能提升并不大。

Macbook Pro M1上的结果

类型 映射 大小 中值时间(ns) 性能提升
i64 HashMap 1 248
i64 HybridMap 1 194 x1.28
i64 HashMap 4 1 117
i64 HybridMap 4 822 x1.36
i64 HashMap 16 4 581
i64 HybridMap 16 3 241 x1.41
i64 HashMap 128 36 593
i64 HybridMap 128 36 629 x1.0
uuid HashMap 1 335
uuid HybridMap 1 235 x1.43
uuid HashMap 4 1 610
uuid HybridMap 4 941 x1.71
uuid HashMap 16 6 346
uuid HybridMap 16 6 424 x0.99
uuid HashMap 128 49 799
uuid HybridMap 128 49 841 x1.0
字符串 HashMap 1 1 176
字符串 HybridMap 1 1 113 x1.06
字符串 HashMap 4 5 313
字符串 HybridMap 4 4 695 x1.13
字符串 HashMap 16 21 626
字符串 HybridMap 16 21 009 x1.03
字符串 HashMap 128 156 010
字符串 HybridMap 128 156 880 x0.99

在这个基准测试中,HybridMap在拥有超过16个条目时会内部切换到HashMap。这不是一个非常稳健的基准测试。正确基准测试HybridMap很难,并且需要比实现crate更多的努力。如许可证所述,自行承担风险。

然而,对于短暂的小型映射,性能提升可能更有趣

类型 长度 中值时间(ns) 性能提升
HashMap 1 130
HashMap 2 173
HybridMap 1 50 x2.61
HybridMap 2 174 x0.99
HybridMap 1 53 x2.45
HybridMap 2 80 x2.17
# Run the benchmarks
cargo bench --bench=hybridmap_bench -- --quick --quiet

# Run this command instead if you have more patience
cargo bench --bench=hybridmap_bench

# Open the results in a browser
open target/criterion/report/index.html
# or
xdg-open target/criterion/report/index.html

内存使用

HybridMap具有小的内存开销,向量与哈希映射之间的枚举变体以及堆栈上预分配的向量。

堆栈上的默认向量大小为 8 个条目。您可以通过将向量大小调整为预期存储在映射中的条目数量来节省一点内存。但大向量很快就会浪费资源。考虑保持在 20 以下。

对于包含非常少条目(一到两个)的映射,内存使用量可以比哈希表小一个数量级。否则,内存使用量与正常哈希表相似。

您可以将 benches/hybridmap_memory.rs 文件调整到您的用例中。

# Run the memory benchmark
# You will probably have to run it many times without things in the background
# to get a coherent result.
cargo bench --bench=hybridmap_memory

为什么?

我开始对小型映射进行基准测试,以检查我是否应该将 HashMap 切换为 BTreeMap 以适应我的用例。我还有一个原始的 Vec 实现,尽管对于小型映射来说更快。因此,我出于乐趣制作了这个包。

这个包可能带来的能源节约可能无法弥补我在实现这个包时为泡茶而烧水的能源消耗。但很有趣。

许可证

本项目采用 Apache License,版本 2.0 - 有关详细信息,请参阅 LICENSE 文件。

致谢

依赖项

~415KB