From ae8f08ce953f3603ce103b4bf6d413c3045a6628 Mon Sep 17 00:00:00 2001 From: Christopher Berner Date: Mon, 16 Dec 2024 10:55:23 -0800 Subject: [PATCH] Add Database::cache_stats() When the "cache_metrics" feature is enable this exposes the number of cache evictions --- src/db.rs | 24 +++++++++++++++++++++++ src/lib.rs | 4 ++-- src/tree_store/page_store/cached_file.rs | 24 ++++++++++++++++++++++- src/tree_store/page_store/page_manager.rs | 6 +++++- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/db.rs b/src/db.rs index 7c12dc3b..ed1a2ebd 100644 --- a/src/db.rs +++ b/src/db.rs @@ -211,6 +211,23 @@ impl<'a, K: Key + 'static, V: Key + 'static> Display for MultimapTableDefinition } } +/// Information regarding the usage of the in-memory cache +/// +/// Note: these metrics are only collected when the "`cache_metrics`" feature is enabled +#[derive(Debug)] +pub struct CacheStats { + pub(crate) evictions: u64, +} + +impl CacheStats { + /// Number of times that data has been evicted, due to the cache being full + /// + /// To increase the cache size use [`Builder::set_cache_size`] + pub fn evictions(&self) -> u64 { + self.evictions + } +} + pub(crate) struct TransactionGuard { transaction_tracker: Option>, transaction_id: Option, @@ -328,6 +345,13 @@ impl Database { Self::builder().open(path) } + /// Information regarding the usage of the in-memory cache + /// + /// Note: these metrics are only collected when the "`cache_metrics`" feature is enabled + pub fn cache_stats(&self) -> CacheStats { + self.mem.cache_stats() + } + pub(crate) fn get_memory(&self) -> Arc { self.mem.clone() } diff --git a/src/lib.rs b/src/lib.rs index 6b52a59a..b8569c1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,8 +68,8 @@ //! [design]: https://github.com/cberner/redb/blob/master/docs/design.md pub use db::{ - Builder, Database, MultimapTableDefinition, MultimapTableHandle, RepairSession, StorageBackend, - TableDefinition, TableHandle, UntypedMultimapTableHandle, UntypedTableHandle, + Builder, CacheStats, Database, MultimapTableDefinition, MultimapTableHandle, RepairSession, + StorageBackend, TableDefinition, TableHandle, UntypedMultimapTableHandle, UntypedTableHandle, }; pub use error::{ CommitError, CompactionError, DatabaseError, Error, SavepointError, StorageError, TableError, diff --git a/src/tree_store/page_store/cached_file.rs b/src/tree_store/page_store/cached_file.rs index 61e03cc9..45cc9d2f 100644 --- a/src/tree_store/page_store/cached_file.rs +++ b/src/tree_store/page_store/cached_file.rs @@ -1,6 +1,6 @@ use crate::tree_store::page_store::base::PageHint; use crate::tree_store::page_store::lru_cache::LRUCache; -use crate::{DatabaseError, Result, StorageBackend, StorageError}; +use crate::{CacheStats, DatabaseError, Result, StorageBackend, StorageError}; use std::ops::{Index, IndexMut}; use std::slice::SliceIndex; #[cfg(feature = "cache_metrics")] @@ -187,6 +187,8 @@ pub(super) struct PagedCachedFile { reads_total: AtomicU64, #[cfg(feature = "cache_metrics")] reads_hits: AtomicU64, + #[cfg(feature = "cache_metrics")] + evictions: AtomicU64, read_cache: Vec>>>, // TODO: maybe move this cache to WriteTransaction? write_buffer: Arc>, @@ -214,11 +216,23 @@ impl PagedCachedFile { reads_total: Default::default(), #[cfg(feature = "cache_metrics")] reads_hits: Default::default(), + #[cfg(feature = "cache_metrics")] + evictions: Default::default(), read_cache, write_buffer: Arc::new(Mutex::new(LRUWriteCache::new())), }) } + #[allow(clippy::unused_self)] + pub(crate) fn cache_stats(&self) -> CacheStats { + CacheStats { + #[cfg(not(feature = "cache_metrics"))] + evictions: 0, + #[cfg(feature = "cache_metrics")] + evictions: self.evictions.load(Ordering::Acquire), + } + } + pub(crate) fn check_io_errors(&self) -> Result { self.file.check_failure() } @@ -329,6 +343,10 @@ impl PagedCachedFile { if cache_size + len > self.max_read_cache_bytes { while removed < len { if let Some((_, v)) = write_lock.pop_lowest_priority() { + #[cfg(feature = "cache_metrics")] + { + self.evictions.fetch_add(1, Ordering::Relaxed); + } removed += v.len(); } else { break; @@ -415,6 +433,10 @@ impl PagedCachedFile { result?; self.write_buffer_bytes .fetch_sub(removed_len, Ordering::Release); + #[cfg(feature = "cache_metrics")] + { + self.evictions.fetch_add(1, Ordering::Relaxed); + } removed_bytes += removed_len; } else { break; diff --git a/src/tree_store/page_store/page_manager.rs b/src/tree_store/page_store/page_manager.rs index abb02f70..5b7bd148 100644 --- a/src/tree_store/page_store/page_manager.rs +++ b/src/tree_store/page_store/page_manager.rs @@ -9,7 +9,7 @@ use crate::tree_store::page_store::layout::DatabaseLayout; use crate::tree_store::page_store::region::{Allocators, RegionTracker}; use crate::tree_store::page_store::{hash128_with_seed, PageImpl, PageMut}; use crate::tree_store::{Page, PageNumber}; -use crate::StorageBackend; +use crate::{CacheStats, StorageBackend}; use crate::{DatabaseError, Result, StorageError}; #[cfg(feature = "logging")] use log::warn; @@ -274,6 +274,10 @@ impl TransactionalMemory { }) } + pub(crate) fn cache_stats(&self) -> CacheStats { + self.storage.cache_stats() + } + pub(crate) fn check_io_errors(&self) -> Result { self.storage.check_io_errors() }