Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statistics for metrics #234

Open
yanns opened this issue Feb 27, 2023 · 3 comments · May be fixed by #262
Open

Statistics for metrics #234

yanns opened this issue Feb 27, 2023 · 3 comments · May be fixed by #262
Labels
enhancement New feature or request question Further information is requested
Milestone

Comments

@yanns
Copy link

yanns commented Feb 27, 2023

I'm wondering if we can expose metrics about a Cache, like caffeine does.

Currently, it's difficult to observe the impact of tuning the cache size and the eviction policies.

@tatsuya6502
Copy link
Member

Hi. Currently Cache does not provide built-in statistics. I tried to implement it a while ago but did not have time to finish it. I will try again in the future.

For now, please collect the statistics by yourself. Here is an example:

use std::sync::atomic::{AtomicU64, Ordering};

use moka::sync::Cache;
use once_cell::sync::Lazy;

fn main() {
    // To record the number of evictions, create an eviction listener.
    let listener = |_k, _v, cause| {
        use moka::notification::RemovalCause;

        // RemovalCause::Size means that the cache reached its maximum capacity
        // and had to evict an entry.
        //
        // For other causes, please see:
        // https://docs.rs/moka/*/moka/notification/enum.RemovalCause.html
        if cause == RemovalCause::Size {
            CACHE_STATS.record_eviction();
        }
    };

    // Create a cache with the eviction listener.
    let cache = Cache::builder()
        .max_capacity(100)
        .eviction_listener(listener)
        .build();

    // Insert 1000 entries into the cache with the max capacity of 100.
    for i in 0..1000 {
        get_or_insert(&cache, i % 250);
    }

    // For the sake of this example, we will call sync() to ensure that all
    // pending tasks (e.g. evictions) are processed. In a real application, you
    // do not have to call it as the Cache will periodically call it for you.
    use moka::sync::ConcurrentCacheExt;
    cache.sync();

    println!("{:?}", *CACHE_STATS);
    // => CacheStats { hits: 600, misses: 400, evictions: 300 }
}

fn get_or_insert(cache: &Cache<i32, i32>, key: i32) -> i32 {
    let entry = cache.entry(key).or_insert_with(|| key);

    if entry.is_fresh() {
        // The entry was just inserted into the cache.
        CACHE_STATS.record_miss();
    } else {
        // The entry was already in the cache.
        CACHE_STATS.record_hit();
    }

    entry.into_value()
}

static CACHE_STATS: Lazy<CacheStats> = Lazy::new(CacheStats::default);

#[derive(Debug, Default)]
pub struct CacheStats {
    hits: AtomicU64,
    misses: AtomicU64,
    evictions: AtomicU64,
}

impl CacheStats {
    pub fn record_hit(&self) {
        self.hits.fetch_add(1, Ordering::AcqRel);
    }

    pub fn record_miss(&self) {
        self.misses.fetch_add(1, Ordering::AcqRel);
    }

    pub fn record_eviction(&self) {
        self.evictions.fetch_add(1, Ordering::AcqRel);
    }
}

@tatsuya6502 tatsuya6502 added the question Further information is requested label Mar 4, 2023
@yanns
Copy link
Author

yanns commented Mar 6, 2023

thanks for the detailed info @tatsuya6502
This is very useful! ❤️

@tatsuya6502 tatsuya6502 added the enhancement New feature or request label Mar 25, 2023
@tatsuya6502 tatsuya6502 added this to the Backlog milestone Mar 25, 2023
@tatsuya6502 tatsuya6502 linked a pull request May 4, 2023 that will close this issue
@tatsuya6502
Copy link
Member

I tried to implement it a while ago but did not have time to finish it. I will try again in the future.

I started to work on it via #262.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
Status: Todo
Development

Successfully merging a pull request may close this issue.

2 participants