9 个版本
0.3.3 | 2024 年 3 月 17 日 |
---|---|
0.3.2 | 2023 年 2 月 6 日 |
0.3.1 | 2023 年 1 月 21 日 |
0.2.2 | 2023 年 1 月 15 日 |
0.1.1 | 2023 年 1 月 7 日 |
#285 在 数据库接口 中
每月 39 次下载
105KB
2.5K SLoC
DiskLRU
DiskLRU 是一个用 Rust 实现的实验性 LRU 存储。
它作为一个简单的键值存储,由 sled 提供支持,sled 是一个轻量级的纯 Rust 高性能事务嵌入式数据库。
它通过给定一个数字自动过期条目,遵循 LRU(最近最少使用)策略,这是一个相当常见的缓存替换策略。
它有一定的成本,但有时比仅在 FIFO 模式(先进先出)中过期旧键更合适,因为您可能有一个很久以前就引入存储中的键值对,但它仍然相关。使用 DiskLRU,如果您的代码经常读取值,它将确保键保持活跃,不会消失。
- HashLRU 在设计上非常相似,充当内存缓存,而 DiskLRU 是一个持久存储。
- MenhirKV 解决了 DiskLRU 所解决的同一个问题,即“存储东西,保留最常用的值,丢弃其余的”。它以一种不那么严格和精确的方式做到这一点,但效率更高。
状态
目前这是一个玩具项目,显然不适用于生产使用。
它至少有两个显著的缺陷
- 与其他替代方案相比,它非常(非常)慢,正是这一点促使我开始开发 MenhirKV,它对过期的处理方法更加实用。
- 它存在严重的稳定性问题,例如,在我的基于 arm64 的笔记本电脑上开启磁盘写入(例如:不使用临时存储)会导致基准测试直接挂起,表现出死锁的症状。
使用
use disklru::Store;
let mut store = Store::open_temporary(4).unwrap();
store.insert(&1, &10).unwrap();
store.insert(&2, &20).unwrap();
store.insert(&3, &30).unwrap();
store.insert(&4, &40).unwrap();
store.insert(&5, &50).unwrap();
// key1 has been dropped, size is limited to 4
assert_eq!(Some(2), store.lru().unwrap());
assert_eq!(Some(20), store.get(&2).unwrap());
// getting key2 has made key3 the least recently used item
assert_eq!(Some(3), store.lru().unwrap());
assert_eq!(Some(40), store.get(&4).unwrap());
// getting key4 makes it the most recently used item
assert_eq!("[3: 30, 5: 50, 2: 20, 4: 40]", format!("{}", store));
store.flush().unwrap(); // commit
基准测试
来自一个随机的 CI 作业
running 12 tests
test tests::bench_read_usize_disklru_compress ... bench: 169,738 ns/iter (+/- 21,901)
test tests::bench_read_usize_disklru_persistent ... bench: 111,211 ns/iter (+/- 12,312)
test tests::bench_read_usize_disklru_temporary ... bench: 105,257 ns/iter (+/- 25,468)
test tests::bench_read_usize_hashlru ... bench: 157 ns/iter (+/- 16)
test tests::bench_read_usize_hashmap ... bench: 40 ns/iter (+/- 10)
test tests::bench_read_usize_lru ... bench: 34 ns/iter (+/- 15)
test tests::bench_write_usize_disklru_compress ... bench: 151,871 ns/iter (+/- 15,723)
test tests::bench_write_usize_disklru_persistent ... bench: 100,999 ns/iter (+/- 5,399)
test tests::bench_write_usize_disklru_temporary ... bench: 95,390 ns/iter (+/- 15,908)
test tests::bench_write_usize_hashlru ... bench: 239 ns/iter (+/- 32)
test tests::bench_write_usize_hashmap ... bench: 117 ns/iter (+/- 26)
test tests::bench_write_usize_lru ... bench: 84 ns/iter (+/- 25)
test result: ok. 0 passed; 0 failed; 0 ignored; 12 measured; 0 filtered out; finished in 98.17s
这不是广泛的、彻底的基准测试的结果,而是一段开发历史中某个时间点的随机快照。
TL;DR -> 性能不佳。
诚然,比较的是非持久性LRU缓存,因此预期会有“一些性能损失”,但差距在这里非常巨大。我启动的另一个项目,使用Bloom过滤器来过期旧条目,大约比这个快10倍。
运行基准测试
cd bench
rustup default nightly
cargo bench
链接
- crate 在crates.io
- doc 在docs.rs
- source 在gitlab.com
- sled,这个LRU存储背后的数据库
- HashLRU,一个类似的内存缓存
- MenhirKV,推荐替代品
许可证
DiskLRU采用MIT许可证。
依赖项
~6MB
~107K SLoC