diff --git a/pageserver/src/metrics.rs b/pageserver/src/metrics.rs index 8f85488aec..db5bccdbba 100644 --- a/pageserver/src/metrics.rs +++ b/pageserver/src/metrics.rs @@ -130,6 +130,79 @@ pub static MATERIALIZED_PAGE_CACHE_HIT: Lazy = Lazy::new(|| { .expect("failed to define a metric") }); +pub struct PageCacheMetrics { + pub read_accesses_materialized_page: IntCounter, + pub read_accesses_ephemeral: IntCounter, + pub read_accesses_immutable: IntCounter, + + pub read_hits_ephemeral: IntCounter, + pub read_hits_immutable: IntCounter, + pub read_hits_materialized_page_exact: IntCounter, + pub read_hits_materialized_page_older_lsn: IntCounter, +} + +static PAGE_CACHE_READ_HITS: Lazy = Lazy::new(|| { + register_int_counter_vec!( + "pageserver_page_cache_read_hits_total", + "Number of read accesses to the page cache that hit", + &["key_kind", "hit_kind"] + ) + .expect("failed to define a metric") +}); + +static PAGE_CACHE_READ_ACCESSES: Lazy = Lazy::new(|| { + register_int_counter_vec!( + "pageserver_page_cache_read_accesses_total", + "Number of read accesses to the page cache", + &["key_kind"] + ) + .expect("failed to define a metric") +}); + +pub static PAGE_CACHE: Lazy = Lazy::new(|| PageCacheMetrics { + read_accesses_materialized_page: { + PAGE_CACHE_READ_ACCESSES + .get_metric_with_label_values(&["materialized_page"]) + .unwrap() + }, + + read_accesses_ephemeral: { + PAGE_CACHE_READ_ACCESSES + .get_metric_with_label_values(&["ephemeral"]) + .unwrap() + }, + + read_accesses_immutable: { + PAGE_CACHE_READ_ACCESSES + .get_metric_with_label_values(&["immutable"]) + .unwrap() + }, + + read_hits_ephemeral: { + PAGE_CACHE_READ_HITS + .get_metric_with_label_values(&["ephemeral", "-"]) + .unwrap() + }, + + read_hits_immutable: { + PAGE_CACHE_READ_HITS + .get_metric_with_label_values(&["immutable", "-"]) + .unwrap() + }, + + read_hits_materialized_page_exact: { + PAGE_CACHE_READ_HITS + .get_metric_with_label_values(&["materialized_page", "exact"]) + .unwrap() + }, + + read_hits_materialized_page_older_lsn: { + PAGE_CACHE_READ_HITS + .get_metric_with_label_values(&["materialized_page", "older_lsn"]) + .unwrap() + }, +}); + static WAIT_LSN_TIME: Lazy = Lazy::new(|| { register_histogram_vec!( "pageserver_wait_lsn_seconds", diff --git a/pageserver/src/page_cache.rs b/pageserver/src/page_cache.rs index d2fe06697e..ef0e748d10 100644 --- a/pageserver/src/page_cache.rs +++ b/pageserver/src/page_cache.rs @@ -313,6 +313,10 @@ impl PageCache { key: &Key, lsn: Lsn, ) -> Option<(Lsn, PageReadGuard)> { + crate::metrics::PAGE_CACHE + .read_accesses_materialized_page + .inc(); + let mut cache_key = CacheKey::MaterializedPage { hash_key: MaterializedPageHashKey { tenant_id, @@ -323,8 +327,21 @@ impl PageCache { }; if let Some(guard) = self.try_lock_for_read(&mut cache_key) { - if let CacheKey::MaterializedPage { hash_key: _, lsn } = cache_key { - Some((lsn, guard)) + if let CacheKey::MaterializedPage { + hash_key: _, + lsn: available_lsn, + } = cache_key + { + if available_lsn == lsn { + crate::metrics::PAGE_CACHE + .read_hits_materialized_page_exact + .inc(); + } else { + crate::metrics::PAGE_CACHE + .read_hits_materialized_page_older_lsn + .inc(); + } + Some((available_lsn, guard)) } else { panic!("unexpected key type in slot"); } @@ -499,11 +516,31 @@ impl PageCache { /// ``` /// fn lock_for_read(&self, cache_key: &mut CacheKey) -> anyhow::Result { + let (read_access, hit) = match cache_key { + CacheKey::MaterializedPage { .. } => { + unreachable!("Materialized pages use lookup_materialized_page") + } + CacheKey::EphemeralPage { .. } => ( + &crate::metrics::PAGE_CACHE.read_accesses_ephemeral, + &crate::metrics::PAGE_CACHE.read_hits_ephemeral, + ), + CacheKey::ImmutableFilePage { .. } => ( + &crate::metrics::PAGE_CACHE.read_accesses_immutable, + &crate::metrics::PAGE_CACHE.read_hits_immutable, + ), + }; + read_access.inc(); + + let mut is_first_iteration = true; loop { // First check if the key already exists in the cache. if let Some(read_guard) = self.try_lock_for_read(cache_key) { + if is_first_iteration { + hit.inc(); + } return Ok(ReadBufResult::Found(read_guard)); } + is_first_iteration = false; // Not found. Find a victim buffer let (slot_idx, mut inner) = diff --git a/test_runner/fixtures/metrics.py b/test_runner/fixtures/metrics.py index 7ee3c33f92..a2bc2e28e5 100644 --- a/test_runner/fixtures/metrics.py +++ b/test_runner/fixtures/metrics.py @@ -59,6 +59,8 @@ PAGESERVER_GLOBAL_METRICS: Tuple[str, ...] = ( "libmetrics_tracing_event_count_total", "pageserver_materialized_cache_hits_total", "pageserver_materialized_cache_hits_direct_total", + "pageserver_page_cache_read_hits_total", + "pageserver_page_cache_read_accesses_total", "pageserver_getpage_reconstruct_seconds_bucket", "pageserver_getpage_reconstruct_seconds_count", "pageserver_getpage_reconstruct_seconds_sum",