| Crates.io | expire_cache |
| lib.rs | expire_cache |
| version | 0.1.25 |
| created_at | 2025-12-02 15:09:34.221233+00 |
| updated_at | 2025-12-20 01:00:46.667852+00 |
| description | High-performance generational cache for Rust / 高性能分代缓存 |
| homepage | https://github.com/js0-site/rust/tree/main/expire_cache |
| repository | https://github.com/js0-site/rust.git |
| max_upload_size | |
| id | 1962031 |
| size | 50,835 |
expire_cache implements an efficient expiration cache using generational collection strategy. Instead of tracking individual item expiration times, it maintains two data buckets (generations), significantly reducing memory overhead and CPU usage for expiration checks.
get_or_init_async!get, insert, and initialization methods[dependencies]
expire_cache = { version = "0.1.22", features = ["hashmap", "get_or_init_async"] }
Available features:
hashmap: Enable HashMap support (papaya::HashMap)hashset: Enable HashSet support (papaya::HashSet)get_or_init: Enable synchronous initializationget_or_init_async: Enable asynchronous initialization macrouse expire_cache::Expire;
use papaya::HashMap;
use std::time::Duration;
#[tokio::main]
async fn main() {
let cache: Expire<HashMap<&str, &str>> = Expire::new(60);
cache.insert("key", "value");
if let Some(val) = cache.get("key") {
println!("Found: {val}");
}
// Wait for expiration
tokio::time::sleep(Duration::from_secs(120)).await;
assert!(cache.get("key").is_none());
}
use expire_cache::{Expire, get_or_init_async};
use papaya::HashMap;
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
let cache: Expire<HashMap<String, String>> = Expire::new(60);
async fn load_data() -> Result<String, std::io::Error> {
Ok("data_for_user_123".to_string())
}
let value: Result<_, std::io::Error> = get_or_init_async!(cache, "user_123", load_data);
println!("Loaded: {}", value?);
Ok(())
}
use expire_cache::{Expire, GetOrInit};
use papaya::HashMap;
fn main() -> Result<(), std::io::Error> {
let cache: Expire<HashMap<String, String>> = Expire::new(60);
let value = cache.get_or_init("user_123", |key| {
Ok::<_, std::io::Error>(format!("data_for_{key}"))
})?;
println!("Loaded: {value}");
Ok(())
}
use expire_cache::Expire;
use papaya::HashSet;
#[tokio::main]
async fn main() {
let cache: Expire<HashSet<&str>> = Expire::new(60);
cache.insert("active_session", ());
if cache.get("active_session").is_some() {
println!("Session exists");
}
}
Expire<T: Map>new(expire: u64) -> Self: Create cache with expiration period in secondsget(&self, key) -> Option<RefVal>: Retrieve value from cacheinsert(&self, key, val): Insert value into cacheget_or_init(&self, key, func) -> Result<RefVal, E>: Sync initialization (requires get_or_init feature)get_or_init_async! macroget_or_init_async!(cache, key, init_fn) -> Result<Val, E>: Async initialization macro, calls init_fn() only on cache missRust's impl Trait return types create distinct opaque types for each call site. When a closure captures references and returns an impl Future, the compiler cannot unify the Future's lifetime with the closure parameter's lifetime in generic contexts. This causes "lifetime mismatch" errors.
The macro approach bypasses this by inlining the code at the call site, so the async expression is awaited directly without going through a generic callback, naturally avoiding the lifetime inference issues.
This is a known Rust limitation: rust-lang/rust#100013
The cache uses a double-buffer approach with two generations:
expire and 2 * expire secondsThis approach trades absolute precision for significant throughput improvements and reduced memory fragmentation.
MulanPSL-2.0
This project is an open-source component of js0.site ⋅ Refactoring the Internet Plan.
We are redefining the development paradigm of the Internet in a componentized way. Welcome to follow us:
expire_cache 实现了基于分代收集策略的高效过期缓存。它不追踪单个条目的过期时间,而是维护两个数据桶(代),显著降低过期检查的内存开销和 CPU 使用率。
get_or_init_async!get、insert 和初始化接口[dependencies]
expire_cache = { version = "0.1.22", features = ["hashmap", "get_or_init_async"] }
可用特性:
hashmap:启用 HashMap 支持 (papaya::HashMap)hashset:启用 HashSet 支持 (papaya::HashSet)get_or_init:启用同步初始化get_or_init_async:启用异步初始化宏use expire_cache::Expire;
use papaya::HashMap;
use std::time::Duration;
#[tokio::main]
async fn main() {
let cache: Expire<HashMap<&str, &str>> = Expire::new(60);
cache.insert("key", "value");
if let Some(val) = cache.get("key") {
println!("Found: {val}");
}
// 等待过期
tokio::time::sleep(Duration::from_secs(120)).await;
assert!(cache.get("key").is_none());
}
use expire_cache::{Expire, get_or_init_async};
use papaya::HashMap;
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
let cache: Expire<HashMap<String, String>> = Expire::new(60);
async fn load_data() -> Result<String, std::io::Error> {
Ok("data_for_user_123".to_string())
}
let value: Result<_, std::io::Error> = get_or_init_async!(cache, "user_123", load_data);
println!("Loaded: {}", value?);
Ok(())
}
use expire_cache::{Expire, GetOrInit};
use papaya::HashMap;
fn main() -> Result<(), std::io::Error> {
let cache: Expire<HashMap<String, String>> = Expire::new(60);
let value = cache.get_or_init("user_123", |key| {
Ok::<_, std::io::Error>(format!("data_for_{key}"))
})?;
println!("Loaded: {value}");
Ok(())
}
use expire_cache::Expire;
use papaya::HashSet;
#[tokio::main]
async fn main() {
let cache: Expire<HashSet<&str>> = Expire::new(60);
cache.insert("active_session", ());
if cache.get("active_session").is_some() {
println!("Session exists");
}
}
Expire<T: Map>new(expire: u64) -> Self:创建带过期周期的缓存(秒)get(&self, key) -> Option<RefVal>:从缓存检索值insert(&self, key, val):向缓存插入值get_or_init(&self, key, func) -> Result<RefVal, E>:同步初始化(需要 get_or_init feature)get_or_init_async! 宏get_or_init_async!(cache, key, init_fn) -> Result<Val, E>:异步初始化宏,仅在缓存未命中时调用 init_fn()Rust 的 impl Trait 返回类型在每个调用点会生成不同的 opaque type。当闭包捕获引用并返回 impl Future 时,编译器无法在泛型上下文中统一 Future 的生命周期与闭包参数的生命周期,导致"生命周期不匹配"错误。
宏通过在调用点内联代码来绕过这个问题,异步表达式直接被 await,无需经过泛型回调,自然避免了生命周期推断问题。
这是 Rust 的已知限制:rust-lang/rust#100013
缓存使用双缓冲方法,包含两个代:
expire 到 2 * expire 秒之间这种方法牺牲了绝对精度,换取了显著的吞吐量提升和内存碎片减少。
MulanPSL-2.0
本项目为 js0.site ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: