Skip to main content

LruBlockCache

Struct LruBlockCache 

Source
pub struct LruBlockCache { /* private fields */ }
Expand description

Bounded LRU. Uses a doubly-linked list of node indices plus a hashmap for O(1) lookup. The list is implemented over a Vec<Node> to avoid the allocator overhead of Box<Node> per insert.

Single-threaded under the hood; the trait advertises Sync via an internal mutex so the cache can be shared across reader threads.

Implementations§

Source§

impl LruBlockCache

Source

pub fn new(capacity: usize) -> Self

Examples found in repository?
examples/perf_features.rs (line 557)
555    fn filled(n: usize) -> (LruBlockCache, usize) {
556        let cap = (n / KEYS_PER_BLOCK).max(64);
557        let cache = LruBlockCache::new(cap);
558        let block: Block = Arc::from(representative_block().into_boxed_slice());
559        for i in 0..cap as u64 {
560            cache.put(BlockKey::new(i % 8, i * BLOCK_BYTES as u64), block.clone());
561        }
562        (cache, cap)
563    }
More examples
Hide additional examples
examples/sample_app.rs (line 312)
309fn block_cache_read_path() {
310    use subms_lsm_tree::{Block, BlockCache, BlockKey, LruBlockCache};
311    println!("\n== block-cache-integration: read-side block cache ==");
312    let cache = LruBlockCache::new(2);
313    let hot = BlockKey::new(1, 0);
314
315    assert!(cache.get(&hot).is_none(), "cold: a miss");
316    cache.put(hot, Block::from(b"AAPL block".as_slice()));
317    let served = cache.get(&hot).expect("warm: a hit");
318    println!(
319        "  {} hit / {} miss after one warm read",
320        cache.hits(),
321        cache.misses()
322    );
323    assert_eq!(&*served, b"AAPL block", "the cached payload is served");
324
325    // A third distinct block evicts the least-recently-used entry (cap 2).
326    cache.put(BlockKey::new(2, 0), Block::from(b"MSFT block".as_slice()));
327    cache.put(BlockKey::new(3, 0), Block::from(b"GOOG block".as_slice()));
328    assert!(
329        cache.get(&hot).is_none(),
330        "coldest block evicted at capacity"
331    );
332}
Source

pub fn capacity(&self) -> usize

Source

pub fn hits(&self) -> u64

Examples found in repository?
examples/sample_app.rs (line 320)
309fn block_cache_read_path() {
310    use subms_lsm_tree::{Block, BlockCache, BlockKey, LruBlockCache};
311    println!("\n== block-cache-integration: read-side block cache ==");
312    let cache = LruBlockCache::new(2);
313    let hot = BlockKey::new(1, 0);
314
315    assert!(cache.get(&hot).is_none(), "cold: a miss");
316    cache.put(hot, Block::from(b"AAPL block".as_slice()));
317    let served = cache.get(&hot).expect("warm: a hit");
318    println!(
319        "  {} hit / {} miss after one warm read",
320        cache.hits(),
321        cache.misses()
322    );
323    assert_eq!(&*served, b"AAPL block", "the cached payload is served");
324
325    // A third distinct block evicts the least-recently-used entry (cap 2).
326    cache.put(BlockKey::new(2, 0), Block::from(b"MSFT block".as_slice()));
327    cache.put(BlockKey::new(3, 0), Block::from(b"GOOG block".as_slice()));
328    assert!(
329        cache.get(&hot).is_none(),
330        "coldest block evicted at capacity"
331    );
332}
Source

pub fn misses(&self) -> u64

Examples found in repository?
examples/sample_app.rs (line 321)
309fn block_cache_read_path() {
310    use subms_lsm_tree::{Block, BlockCache, BlockKey, LruBlockCache};
311    println!("\n== block-cache-integration: read-side block cache ==");
312    let cache = LruBlockCache::new(2);
313    let hot = BlockKey::new(1, 0);
314
315    assert!(cache.get(&hot).is_none(), "cold: a miss");
316    cache.put(hot, Block::from(b"AAPL block".as_slice()));
317    let served = cache.get(&hot).expect("warm: a hit");
318    println!(
319        "  {} hit / {} miss after one warm read",
320        cache.hits(),
321        cache.misses()
322    );
323    assert_eq!(&*served, b"AAPL block", "the cached payload is served");
324
325    // A third distinct block evicts the least-recently-used entry (cap 2).
326    cache.put(BlockKey::new(2, 0), Block::from(b"MSFT block".as_slice()));
327    cache.put(BlockKey::new(3, 0), Block::from(b"GOOG block".as_slice()));
328    assert!(
329        cache.get(&hot).is_none(),
330        "coldest block evicted at capacity"
331    );
332}

Trait Implementations§

Source§

impl BlockCache for LruBlockCache

Source§

fn get(&self, key: &BlockKey) -> Option<Block>

Returns the cached payload if present.
Source§

fn put(&self, key: BlockKey, block: Block)

Insert a block. May evict to honour capacity bounds.
Source§

fn len(&self) -> usize

Current number of cached entries.
Source§

fn clear(&self)

Drop every entry. Used by tests + manifest swaps.
Source§

fn is_empty(&self) -> bool

True if no entries are cached.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.