#hash-map #serde #lock #concurrency #hash-key #parking-lot #locking

chashmap-serde

快速、支持广泛API和Serde的并发哈希表

3个版本 (1个稳定版本)

2.2.3 2022年10月16日
0.1.1 2022年10月10日
0.1.0 2022年10月9日

#906 in 编码

MIT 许可证

74KB
1.5K SLoC

Rust Dependency Review Crate API

并发哈希表。

这是对 https://gitlab.redox-os.org/redox-os/chashmap 的克隆,当时似乎没有太多维护。 我并不认为原始作者的辛勤工作应该得到认可。 我的贡献是添加serde支持以及我可能需要的其他功能。

该crate实现了基于桶级别多读锁的并发哈希表,具有卓越的性能特征¹,并支持调整大小、原地修改等。

API直接从 std::collections::HashMap 继承而来,使其感觉非常熟悉。

¹请注意,它很大程度上依赖于您程序的行为,但在大多数情况下,它非常好。在某些(罕见)情况下,您可能需要原子哈希表。

工作原理

chashmap 不是无锁的,但它将锁分布在整个映射中,使得锁竞争(这可能会使访问变得昂贵)非常罕见。

哈希表由所谓的“桶”组成,每个桶定义了表中的潜在条目。某些键值对的桶由键的哈希值确定。通过为每个桶保持读写锁,我们确保您通常只需一个或两个锁定子程序即可插入、读取、修改等。

特殊情况:重新分配。当表被填满,几乎没有空闲桶(注意,这“几乎没有”而不是“没有”,因为负载因子不应太高,因为这会损害性能)时,在重新散列表时获得全局锁。这非常低效,但这种情况很少发生,并且由于容量具有适应性,当映射刚刚初始化时,它只会发生几次。

冲突解决

当两个哈希值发生冲突时,它们不能共享同一个桶,因此必须有一个算法可以解决冲突。在我们的情况下,我们使用线性探测,这意味着我们取紧随其后的桶,并重复直到找到空闲的桶。

这种方法远非理想,但像Robin-Hood哈希这样的更优方法在并发结构中效果不佳(如果有的话)。

API

如果您熟悉libstd哈希表实现,那么API应该感觉非常熟悉。它们共享许多方法,并且我已经仔细确保所有在libstd中有相似名称的项目在语义和行为上是一致的。

Serde

已添加对Serde的支持,并应与您选择的任何Serde序列化器/反序列化器一起工作。

fn main() {
 //================================================================================
 // serialize
 //================================================================================
 let cmap1 = CHashMap::<String, String>::new();
 cmap1.insert("key1".to_string(), "val1".to_string());
 cmap1.insert("key2".to_string(), "val2".to_string());

 let j1 = serde_json::to_string(&cmap1);
 assert!(j1.is_ok());

 //================================================================================
 // deserialize
 //================================================================================
 let j1 = j1.unwrap();
 let cmap1x: CHashMap<String, String> = serde_json::from_str(j1.as_str()).unwrap();

 assert_eq!(*cmap1.get("key1").unwrap(), *cmap1x.get("key1").unwrap());
 assert_eq!(*cmap1.get("key2").unwrap(), *cmap1x.get("key2").unwrap());
}

依赖项

~0.9–6.5MB
~36K SLoC