1个不稳定版本
0.1.0-alpha | 2022年11月30日 |
---|
#197 in 缓存
115KB
2.5K SLoC
memory-cache-rust
memory-cache是一个以性能和正确性为重点构建的快速、并发缓存库。
构建memory-cache的动机来自于在Dgraph中需要无竞争的缓存。
功能
- 高命中率 - 使用我们独特的准入/淘汰策略配对,Ristretto的性能在同类中最佳。
- 淘汰:SampledLFU - 与精确LRU相当,在搜索和数据库跟踪上性能更好。
- 准入:TinyLFU - 有一点内存开销(每个计数器12位),但性能提升。
- 高速吞吐量 - 我们使用各种技术来管理竞争,结果是卓越的吞吐量。
- 基于成本的淘汰 - 任何被认为有价值的大项可以淘汰多个较小的项(成本可以是任何东西)。
- 完全并发 - 你可以使用尽可能多的线程,吞吐量下降很小。
- 指标 - 可选的性能指标,包括吞吐量、HIT比率和其他统计数据。
- 简单API - 只需确定你的理想
Config
值,然后就可以开始运行。
状态
Ristretto可用于生产,但仍在积极开发中。我们预计它将在不久的将来准备好用于生产。
用法
示例
use memory_cache_rust::bloom::hasher::{key_to_hash, cast_mut, value_to_int};
fn main() {
let cache = Cache::with_config(
Config {
numb_counters: 1e7 as i64, // maximum cost of cache (1GB).
max_cost: 1 << 30,// maximum cost of cache (1GB).
buffer_items: 64,// number of keys per Get buffer.
metrics: false,
key_to_hash: key_to_hash,
on_evict: None,
cost: None,
}
);
let guard = cache.guard();
cache.set("key", "value1", 1, &guard);
cache.set("key2", "value2", 1, &guard);
cache.set("key3", "value3", 1, &guard);
cache.set("key4", "value4", 1, &guard);
thread::sleep(Duration::from_millis(50));
assert_eq!(cache.get(&"key", &guard), Some("value1"));
assert_eq!(cache.get(&"key2", &guard), Some("value2"));
assert_eq!(cache.get(&"key3", &guard), Some("value3"));
cache.del("key", &guard);
thread::sleep(Duration::from_millis(10));
let v = cache.get(&"key", &guard);
assert_eq!(v, None);
}
配置
在创建Ristretto实例时,将Config
结构传递给NewCache
(如上例所示)。
NumCounters int64
NumCounters是要保留的4位访问计数器的数量,用于准入和淘汰。当缓存满时,我们将此设置为预期保留项数的10倍时看到良好的性能。
例如,如果每个项的成本为1且MaxCost为100,则将NumCounters设置为1,000。或者,如果您使用可变成本值但预计缓存满时将保留约10,000个项,则将NumCounters设置为100,000。重要的是在满的缓存中的唯一项数,而不一定是MaxCost值。
MaxCost int64
MaxCost决定了驱逐决策。例如,如果MaxCost是100,并且一个成本为1的新项目将总缓存成本增加到101,则会驱逐1个项目。
MaxCost还可以用来表示字节的最大大小。例如,如果MaxCost是1,000,000(1MB),且缓存已满,有1,000个1KB的项目,一个新接受的项目将导致5个1KB的项目被驱逐。
MaxCost可以是任何值,只要它与调用Set时使用的成本值匹配。
BufferItems int64
BufferItems是Get缓冲区的大小。我们找到的最佳值是64。
如果在某些原因下你看到Get性能随着大量竞争(你不应该)而下降,尝试以64的倍数增加此值。这是一个微调机制,你可能不必接触它。
Metrics bool
当你想要实时记录各种统计信息时,Metrics为true。这是因为这是一个配置标志,存在10%的吞吐量性能开销。
OnEvict func(hashes [2]uint64, value interface{}, cost int64)
对于每次驱逐,都会调用OnEvict。
KeyToHash func(key interface{}) [2]uint64
KeyToHash是用于每个键的哈希算法。如果这是nil,
注意,如果你想使用128位哈希,你应该使用完整的[2]uint64
,否则只需在uint64
的0
位置填充,它将像任何64位哈希一样运行。
Cost func(value interface{}) int64
Cost是一个可选函数,你可以将其传递给Config,以在运行时评估项目成本,并且仅用于不丢弃的Set调用(如果计算项目成本特别昂贵,并且你不希望浪费时间在将被丢弃的项目上,这很有用)。
要通知Ristretto你想要使用此Cost函数
- 将Cost字段设置为一个非nil函数。
- 在调用Set为新项目或项目更新时,使用
cost
为0。
依赖项
~6–13MB
~127K SLoC