# HashLRU
[HashLRU](https://gitlab.com/liberecofr/hashlru) is an experimental LRU cache implemented in [Rust](https://www.rust-lang.org/).
It tries to follow the API exposed by a [standard Rust HashMap](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html)
while enforcing a limited memory footprint by limiting the number of keys using the LRU (least recently used) strategy, which is
a quite [common cache replacement policy]( https://en.wikipedia.org/wiki/Cache_replacement_policies).

[DiskLRU](https://gitlab.com/liberecofr/disklru) is very similar in its design, and acts
as a persistent store, as opposed to [HashLRU](https://gitlab.com/liberecofr/hashlru) being an in-memory cache.
# Status
For now this is a toy project, clearly *NOT* suitable for production use.
There are many other libraries you could use instead:
* [lru](https://crates.io/crates/lru) is faster, and has support for mutable iterators, among other things. See [doc](https://docs.rs/lru/latest/lru/) and [source](https://github.com/jeromefroe/lru-rs).
* [cached](https://crates.io/crates/cached) comes with batteries included, has support for many other features than just LRU. See [doc](https://docs.rs/cached/latest/cached/) and [source](https://github.com/jaemk/cached).
It is written in 100% safe rust code, and as it uses only a `HashMap` to store data,
and no `RefCell` or pointer or anything, it deals rather nicely with being shared
between threads, moved, etc.
Here is a quick bench done on a 100k items map:
```
$ cargo bench
Finished bench [optimized] target(s) in 0.03s
Running unittests src/lib.rs (target/release/deps/benches-cc4ef79ee8fe94e4)
running 6 tests
test tests::bench_read_usize_hashlru ... bench: 41 ns/iter (+/- 10)
test tests::bench_read_usize_hashmap ... bench: 14 ns/iter (+/- 1)
test tests::bench_read_usize_lru ... bench: 10 ns/iter (+/- 2)
test tests::bench_write_usize_hashlru ... bench: 114 ns/iter (+/- 22)
test tests::bench_write_usize_hashmap ... bench: 65 ns/iter (+/- 13)
test tests::bench_write_usize_lru ... bench: 24 ns/iter (+/- 5)
test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out; finished in 24.36s
```
Those results are not super reliable, just a one-shot test ran on a laptop.
However there is a tendency: `hashlru` is the slowest, `lru` performs best (probably because
it keeps the number of items below 100k) and standard `hashmap` is in between.
Proof this is a toy project.
[](https://gitlab.com/liberecofr/hashlru/pipelines)
# Usage
```rust
use hashlru::Cache;
let mut lru = Cache::new(4);
lru.insert("key1", 10);
lru.insert("key2", 20);
lru.insert("key3", 30);
lru.insert("key4", 40);
lru.insert("key5", 50);
// key1 has been dropped, size is limited to 4
assert_eq!("key2", lru.lru().unwrap());
assert_eq!(Some(&20), lru.get(&"key2"));
// getting key2 has made key3 the least recently used item
assert_eq!("key3", lru.lru().unwrap());
assert_eq!(Some(&40), lru.get(&"key4"));
// getting key4 makes it the most recently used item
assert_eq!("[key3: 30, key5: 50, key2: 20, key4: 40]", format!("{}", lru));
```
# Links
* [crate](https://crates.io/crates/hashlru) on crates.io
* [doc](https://docs.rs/hashlru/) on docs.rs
* [source](https://gitlab.com/liberecofr/hashlru/tree/main) on gitlab.com
* [DiskLRU](https://gitlab.com/liberecofr/disklru), a similar persistent store
# License
HashLRU is licensed under the [MIT](https://gitlab.com/liberecofr/hashlru/blob/main/LICENSE) license.