Skip to content

Commit d17d93a

Browse files
authored
Dix/metrics api (#56)
* refactor: streamline MetricsCell and enhance documentation Removed the `new` method from `MetricsCell` to simplify its usage, as it is now directly initialized with a `Cell<u64>`. Updated the documentation for `metrics_impl.rs` to provide clearer insights into the metrics structures and their visibility, emphasizing the encapsulation of internal metrics management. Added concise summaries for each metrics struct to improve clarity and usability. * feat: add serde support for cache metrics serialization Introduced optional `serde` dependency for cache metrics snapshots, enabling serialization and deserialization of metrics structures. Enhanced documentation for `CacheMetricsSnapshot` and other metrics structs to clarify their purpose and usage, including examples demonstrating serialization capabilities. This change improves usability and facilitates integration with external systems requiring metrics data in a serialized format. * docs: enhance metrics traits documentation with examples and clarity Added example usage for `CoreMetricsRecorder` and its related traits, improving the documentation for cache metrics. Clarified the purpose of each metrics trait and their relationships, including references to mutable and read-only counterparts. This change enhances usability and understanding of the metrics system within the cache library. * fix: update frequency buckets iteration method for accuracy Replaced the `iter_entries` method with `iter` in the frequency buckets property tests to ensure accurate minimum frequency calculations. This change aligns with recent updates to the `FrequencyBuckets` module, enhancing consistency and correctness in the test implementation. * docs: clarify MetricsCell usage in metrics_impl.rs Updated the documentation for `MetricsCell` in `metrics_impl.rs` to include a direct reference to its location within the module. This change enhances clarity regarding the internal structure and visibility of the metrics management system, ensuring users understand the encapsulation of internal metrics management. * docs: refine MetricsCell documentation in metrics_impl.rs Updated the documentation for `MetricsCell` in `metrics_impl.rs` to remove redundant phrasing, enhancing clarity regarding its usage and visibility within the module. This change aims to improve understanding of the internal metrics management system.
1 parent 3b46721 commit d17d93a

8 files changed

Lines changed: 188 additions & 135 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ crate-type = ["lib"]
3535
[features]
3636
default = ["policy-s3-fifo", "policy-lru", "policy-fast-lru", "policy-lru-k", "policy-clock"]
3737
metrics = []
38+
serde = ["dep:serde"]
3839
concurrency = ["parking_lot"]
3940

4041
# Eviction policy feature flags. Enable only the policies you need for smaller builds.
@@ -81,6 +82,7 @@ policy-nru = []
8182
[dependencies]
8283
parking_lot = { version = "0.12", optional = true }
8384
rustc-hash = "2.1"
85+
serde = { version = "1", features = ["derive"], optional = true }
8486

8587
[dev-dependencies]
8688
bench-support = { path = "bench-support" }

fuzz/fuzz_targets/frequency_buckets_property_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ fn test_min_freq_accuracy(data: &[u8]) {
101101

102102
// Compute actual minimum frequency
103103
let mut actual_min: Option<u64> = None;
104-
for (_, meta) in buckets.iter_entries() {
104+
for (_, meta) in buckets.iter() {
105105
actual_min = match actual_min {
106106
None => Some(meta.freq),
107107
Some(min) => Some(min.min(meta.freq)),

src/metrics/cell.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ use std::cell::Cell;
99
pub(crate) struct MetricsCell(Cell<u64>);
1010

1111
impl MetricsCell {
12-
#[inline]
13-
pub fn new() -> Self {
14-
Self(Cell::new(0))
15-
}
16-
1712
#[inline]
1813
pub fn get(&self) -> u64 {
1914
self.0.get()

src/metrics/metrics_impl.rs

Lines changed: 46 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
//! Concrete metrics recorders for each eviction policy.
2+
//!
3+
//! Each struct accumulates lightweight counters that the corresponding policy
4+
//! increments on its hot path. The [`snapshot`](super::snapshot) module provides
5+
//! read-only, `Copy` snapshots of these counters for bench/test consumption,
6+
//! while [`exporter`](super::exporter) publishes them to monitoring backends.
7+
//!
8+
//! ## Field visibility
9+
//!
10+
//! Fields backed by plain `u64` are `pub` for direct reads.
11+
//! Fields that require interior mutability (recorded through `&self` on read
12+
//! paths) use the crate-internal `MetricsCell` and are `pub(crate)`.
13+
114
use crate::metrics::cell::MetricsCell;
215
use crate::metrics::traits::{
316
ArcMetricsRecorder, CarMetricsRecorder, ClockMetricsRecorder, ClockProMetricsRecorder,
@@ -7,7 +20,8 @@ use crate::metrics::traits::{
720
S3FifoMetricsRecorder, SlruMetricsRecorder, TwoQMetricsRecorder,
821
};
922

10-
#[derive(Debug, Default)]
23+
/// FIFO / insertion-order cache metrics.
24+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
1125
pub struct CacheMetrics {
1226
pub get_calls: u64,
1327
pub get_hits: u64,
@@ -29,7 +43,8 @@ pub struct CacheMetrics {
2943
pub(crate) age_rank_found: MetricsCell,
3044
}
3145

32-
#[derive(Debug, Default)]
46+
/// LRU (least-recently-used) cache metrics.
47+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
3348
pub struct LruMetrics {
3449
pub get_calls: u64,
3550
pub get_hits: u64,
@@ -50,7 +65,8 @@ pub struct LruMetrics {
5065
pub(crate) recency_rank_scan_steps: MetricsCell,
5166
}
5267

53-
#[derive(Debug, Default)]
68+
/// LFU (least-frequently-used) cache metrics.
69+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
5470
pub struct LfuMetrics {
5571
pub get_calls: u64,
5672
pub get_hits: u64,
@@ -72,7 +88,8 @@ pub struct LfuMetrics {
7288
pub increment_frequency_found: u64,
7389
}
7490

75-
#[derive(Debug, Default)]
91+
/// LRU-K (K-distance) cache metrics.
92+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
7693
pub struct LruKMetrics {
7794
pub get_calls: u64,
7895
pub get_hits: u64,
@@ -102,31 +119,6 @@ pub struct LruKMetrics {
102119
pub(crate) k_distance_rank_scan_steps: MetricsCell,
103120
}
104121

105-
impl CacheMetrics {
106-
pub fn new() -> CacheMetrics {
107-
Self {
108-
get_calls: 0,
109-
get_hits: 0,
110-
get_misses: 0,
111-
insert_calls: 0,
112-
insert_updates: 0,
113-
insert_new: 0,
114-
evict_calls: 0,
115-
evicted_entries: 0,
116-
stale_skips: 0,
117-
evict_scan_steps: 0,
118-
pop_oldest_calls: 0,
119-
pop_oldest_found: 0,
120-
pop_oldest_empty_or_stale: 0,
121-
peek_oldest_calls: MetricsCell::new(),
122-
peek_oldest_found: MetricsCell::new(),
123-
age_rank_calls: MetricsCell::new(),
124-
age_rank_scan_steps: MetricsCell::new(),
125-
age_rank_found: MetricsCell::new(),
126-
}
127-
}
128-
}
129-
130122
impl CoreMetricsRecorder for CacheMetrics {
131123
fn record_get_hit(&mut self) {
132124
self.get_calls += 1;
@@ -185,6 +177,7 @@ impl FifoMetricsRecorder for CacheMetrics {
185177
}
186178
}
187179

180+
#[doc(hidden)]
188181
impl FifoMetricsReadRecorder for &CacheMetrics {
189182
fn record_peek_oldest_call(&self) {
190183
self.peek_oldest_calls.incr();
@@ -279,6 +272,7 @@ impl LruMetricsRecorder for LruMetrics {
279272
}
280273
}
281274

275+
#[doc(hidden)]
282276
impl LruMetricsReadRecorder for &LruMetrics {
283277
fn record_peek_lru_call(&self) {
284278
self.peek_lru_calls.incr();
@@ -377,6 +371,7 @@ impl LfuMetricsRecorder for LfuMetrics {
377371
}
378372
}
379373

374+
#[doc(hidden)]
380375
impl LfuMetricsReadRecorder for &LfuMetrics {
381376
fn record_peek_lfu_call(&self) {
382377
self.peek_lfu_calls.incr();
@@ -505,6 +500,7 @@ impl LruKMetricsRecorder for LruKMetrics {
505500
}
506501
}
507502

503+
#[doc(hidden)]
508504
impl LruKMetricsReadRecorder for &LruKMetrics {
509505
fn record_peek_lru_k_call(&self) {
510506
self.peek_lru_k_calls.incr();
@@ -535,11 +531,8 @@ impl LruKMetricsReadRecorder for &LruKMetrics {
535531
}
536532
}
537533

538-
// ---------------------------------------------------------------------------
539-
// CoreOnlyMetrics (LIFO, Random)
540-
// ---------------------------------------------------------------------------
541-
542-
#[derive(Debug, Default)]
534+
/// Minimal metrics for policies with no policy-specific counters (LIFO, Random).
535+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
543536
pub struct CoreOnlyMetrics {
544537
pub get_calls: u64,
545538
pub get_hits: u64,
@@ -578,11 +571,8 @@ impl CoreMetricsRecorder for CoreOnlyMetrics {
578571
fn record_clear(&mut self) {}
579572
}
580573

581-
// ---------------------------------------------------------------------------
582-
// ArcMetrics
583-
// ---------------------------------------------------------------------------
584-
585-
#[derive(Debug, Default)]
574+
/// ARC (adaptive replacement cache) metrics.
575+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
586576
pub struct ArcMetrics {
587577
pub get_calls: u64,
588578
pub get_hits: u64,
@@ -652,11 +642,8 @@ impl ArcMetricsRecorder for ArcMetrics {
652642
}
653643
}
654644

655-
// ---------------------------------------------------------------------------
656-
// CarMetrics
657-
// ---------------------------------------------------------------------------
658-
659-
#[derive(Debug, Default)]
645+
/// CAR (clock with adaptive replacement) metrics.
646+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
660647
pub struct CarMetrics {
661648
pub get_calls: u64,
662649
pub get_hits: u64,
@@ -722,11 +709,8 @@ impl CarMetricsRecorder for CarMetrics {
722709
}
723710
}
724711

725-
// ---------------------------------------------------------------------------
726-
// ClockMetrics
727-
// ---------------------------------------------------------------------------
728-
729-
#[derive(Debug, Default)]
712+
/// Clock (second-chance) cache metrics.
713+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
730714
pub struct ClockMetrics {
731715
pub get_calls: u64,
732716
pub get_hits: u64,
@@ -776,11 +760,8 @@ impl ClockMetricsRecorder for ClockMetrics {
776760
}
777761
}
778762

779-
// ---------------------------------------------------------------------------
780-
// ClockProMetrics
781-
// ---------------------------------------------------------------------------
782-
783-
#[derive(Debug, Default)]
763+
/// Clock-PRO (adaptive hot/cold/test clock) metrics.
764+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
784765
pub struct ClockProMetrics {
785766
pub get_calls: u64,
786767
pub get_hits: u64,
@@ -838,11 +819,8 @@ impl ClockProMetricsRecorder for ClockProMetrics {
838819
}
839820
}
840821

841-
// ---------------------------------------------------------------------------
842-
// MfuMetrics
843-
// ---------------------------------------------------------------------------
844-
845-
#[derive(Debug, Default)]
822+
/// MFU (most-frequently-used eviction) metrics.
823+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
846824
pub struct MfuMetrics {
847825
pub get_calls: u64,
848826
pub get_hits: u64,
@@ -908,6 +886,7 @@ impl MfuMetricsRecorder for MfuMetrics {
908886
}
909887
}
910888

889+
#[doc(hidden)]
911890
impl MfuMetricsReadRecorder for &MfuMetrics {
912891
fn record_peek_mfu_call(&self) {
913892
self.peek_mfu_calls.incr();
@@ -923,11 +902,8 @@ impl MfuMetricsReadRecorder for &MfuMetrics {
923902
}
924903
}
925904

926-
// ---------------------------------------------------------------------------
927-
// NruMetrics
928-
// ---------------------------------------------------------------------------
929-
930-
#[derive(Debug, Default)]
905+
/// NRU (not-recently-used) cache metrics.
906+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
931907
pub struct NruMetrics {
932908
pub get_calls: u64,
933909
pub get_hits: u64,
@@ -977,11 +953,8 @@ impl NruMetricsRecorder for NruMetrics {
977953
}
978954
}
979955

980-
// ---------------------------------------------------------------------------
981-
// SlruMetrics
982-
// ---------------------------------------------------------------------------
983-
984-
#[derive(Debug, Default)]
956+
/// SLRU (segmented LRU) cache metrics.
957+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
985958
pub struct SlruMetrics {
986959
pub get_calls: u64,
987960
pub get_hits: u64,
@@ -1031,11 +1004,8 @@ impl SlruMetricsRecorder for SlruMetrics {
10311004
}
10321005
}
10331006

1034-
// ---------------------------------------------------------------------------
1035-
// TwoQMetrics
1036-
// ---------------------------------------------------------------------------
1037-
1038-
#[derive(Debug, Default)]
1007+
/// Two-Q (A1in/A1out/Am queue) cache metrics.
1008+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
10391009
pub struct TwoQMetrics {
10401010
pub get_calls: u64,
10411011
pub get_hits: u64,
@@ -1085,11 +1055,8 @@ impl TwoQMetricsRecorder for TwoQMetrics {
10851055
}
10861056
}
10871057

1088-
// ---------------------------------------------------------------------------
1089-
// S3FifoMetrics
1090-
// ---------------------------------------------------------------------------
1091-
1092-
#[derive(Debug, Default, Clone)]
1058+
/// S3-FIFO (small/main/ghost queue) cache metrics.
1059+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
10931060
pub struct S3FifoMetrics {
10941061
pub get_calls: u64,
10951062
pub get_hits: u64,

0 commit comments

Comments
 (0)