Skip to content

Commit aea5a47

Browse files
committed
Add helper macro for stats increment
1 parent 8f30dd3 commit aea5a47

1 file changed

Lines changed: 54 additions & 66 deletions

File tree

src/cache/multilevel.rs

Lines changed: 54 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ use crate::config::CacheType;
5050
use crate::config::{Config, PreprocessorCacheModeConfig, WriteErrorPolicy};
5151
use crate::errors::*;
5252

53+
/// Increment an atomic stats counter, handling the Option check.
54+
/// Usage: `inc_stat!(optional_stats, field_name, value)`
55+
macro_rules! inc_stat {
56+
($stats:expr, $field:ident, $value:expr) => {
57+
if let Some(s) = $stats {
58+
s.$field.fetch_add($value, Ordering::Relaxed);
59+
}
60+
};
61+
}
62+
5363
/// Lock-free atomic counters for multi-level cache statistics.
5464
/// Stored directly in MultiLevelStorage to avoid mutex contention.
5565
struct AtomicLevelStats {
@@ -357,23 +367,6 @@ impl MultiLevelStorage {
357367
MultiLevelStats(self.atomic_stats.iter().map(|s| s.snapshot()).collect())
358368
}
359369

360-
/// Record a successful write to a level
361-
fn record_write_success(&self, idx: usize, duration: Duration) {
362-
if let Some(stats) = self.atomic_stats.get(idx) {
363-
stats.writes.fetch_add(1, Ordering::Relaxed);
364-
stats
365-
.write_duration_nanos
366-
.fetch_add(duration.as_nanos() as u64, Ordering::Relaxed);
367-
}
368-
}
369-
370-
/// Record a failed write to a level
371-
fn record_write_failure(&self, idx: usize) {
372-
if let Some(stats) = self.atomic_stats.get(idx) {
373-
stats.write_failures.fetch_add(1, Ordering::Relaxed);
374-
}
375-
}
376-
377370
/// Create a multi-level storage from configuration.
378371
///
379372
/// Returns None if no levels are configured (SCCACHE_MULTILEVEL_CHAIN not set).
@@ -550,18 +543,16 @@ impl MultiLevelStorage {
550543
Ok(_) => {
551544
let duration = start.elapsed();
552545
trace!("Backfilled cache level {} on write in {:?}", idx, duration);
553-
if let Some(stats) = stats_arc {
554-
stats.writes.fetch_add(1, Ordering::Relaxed);
555-
stats
556-
.write_duration_nanos
557-
.fetch_add(duration.as_nanos() as u64, Ordering::Relaxed);
558-
}
546+
inc_stat!(stats_arc.as_deref(), writes, 1);
547+
inc_stat!(
548+
stats_arc.as_deref(),
549+
write_duration_nanos,
550+
duration.as_nanos() as u64
551+
);
559552
}
560553
Err(e) => {
561554
debug!("Background write to level {} failed: {}", idx, e);
562-
if let Some(stats) = stats_arc {
563-
stats.write_failures.fetch_add(1, Ordering::Relaxed);
564-
}
555+
inc_stat!(stats_arc.as_deref(), write_failures, 1);
565556
}
566557
}
567558
});
@@ -580,17 +571,15 @@ impl Storage for MultiLevelStorage {
580571
debug!("Cache hit at level {} in {:?}", idx, duration);
581572

582573
// Update stats
583-
if let Some(stats) = self.atomic_stats.get(idx) {
584-
stats.hits.fetch_add(1, Ordering::Relaxed);
585-
stats
586-
.hit_duration_nanos
587-
.fetch_add(duration.as_nanos() as u64, Ordering::Relaxed);
588-
}
574+
inc_stat!(self.atomic_stats.get(idx), hits, 1);
575+
inc_stat!(
576+
self.atomic_stats.get(idx),
577+
hit_duration_nanos,
578+
duration.as_nanos() as u64
579+
);
589580
// Mark misses for all levels checked before this hit
590581
for miss_idx in 0..idx {
591-
if let Some(stats) = self.atomic_stats.get(miss_idx) {
592-
stats.misses.fetch_add(1, Ordering::Relaxed);
593-
}
582+
inc_stat!(self.atomic_stats.get(miss_idx), misses, 1);
594583
}
595584

596585
// If hit at level > 0, backfill to faster levels (L0 to L(idx-1))
@@ -602,11 +591,11 @@ impl Storage for MultiLevelStorage {
602591
match level.get_raw(key).await {
603592
Ok(Some(raw_bytes)) => {
604593
// Update backfill stats
605-
if let Some(stats) = self.atomic_stats.get(hit_level) {
606-
stats
607-
.backfills_from
608-
.fetch_add(idx as u64, Ordering::Relaxed);
609-
}
594+
inc_stat!(
595+
self.atomic_stats.get(hit_level),
596+
backfills_from,
597+
idx as u64
598+
);
610599

611600
// Spawn background backfill tasks for each faster level
612601
// Iterate slice directly instead of creating Vec
@@ -629,11 +618,7 @@ impl Storage for MultiLevelStorage {
629618
backfill_idx, hit_level
630619
);
631620
// Update backfill_to stats
632-
if let Some(stats) = stats_arc {
633-
stats
634-
.backfills_to
635-
.fetch_add(1, Ordering::Relaxed);
636-
}
621+
inc_stat!(stats_arc.as_deref(), backfills_to, 1);
637622
}
638623
Err(e) => {
639624
debug!(
@@ -682,9 +667,7 @@ impl Storage for MultiLevelStorage {
682667

683668
// Mark final miss for all checked levels
684669
for idx in 0..self.levels.len() {
685-
if let Some(stats) = self.atomic_stats.get(idx) {
686-
stats.misses.fetch_add(1, Ordering::Relaxed);
687-
}
670+
inc_stat!(self.atomic_stats.get(idx), misses, 1);
688671
}
689672

690673
Ok(Cache::Miss)
@@ -719,10 +702,15 @@ impl Storage for MultiLevelStorage {
719702
Ok(_) => {
720703
let duration = start.elapsed();
721704
trace!("Stored in cache level 0 in {:?}", duration);
722-
self.record_write_success(0, duration);
705+
inc_stat!(self.atomic_stats.first(), writes, 1);
706+
inc_stat!(
707+
self.atomic_stats.first(),
708+
write_duration_nanos,
709+
duration.as_nanos() as u64
710+
);
723711
}
724712
Err(e) => {
725-
self.record_write_failure(0);
713+
inc_stat!(self.atomic_stats.first(), write_failures, 1);
726714
return Err(e);
727715
}
728716
}
@@ -759,20 +747,20 @@ impl Storage for MultiLevelStorage {
759747
if let Err(e) = result {
760748
// Check if read-only before failing
761749
if !matches!(level.check().await, Ok(CacheMode::ReadOnly)) {
762-
if let Some(stats) = stats_arc {
763-
stats.write_failures.fetch_add(1, Ordering::Relaxed);
764-
}
750+
inc_stat!(stats_arc.as_deref(), write_failures, 1);
765751
return Err(anyhow!(
766752
"Failed to write to cache level {}: {}",
767753
idx,
768754
e
769755
));
770756
}
771-
} else if let Some(stats) = stats_arc {
772-
stats.writes.fetch_add(1, Ordering::Relaxed);
773-
stats
774-
.write_duration_nanos
775-
.fetch_add(duration.as_nanos() as u64, Ordering::Relaxed);
757+
} else {
758+
inc_stat!(stats_arc.as_deref(), writes, 1);
759+
inc_stat!(
760+
stats_arc.as_deref(),
761+
write_duration_nanos,
762+
duration.as_nanos() as u64
763+
);
776764
}
777765
} else {
778766
// L1+ async
@@ -789,16 +777,16 @@ impl Storage for MultiLevelStorage {
789777
if let Err(e) = result {
790778
// Check if read-only before failing
791779
if !matches!(level.check().await, Ok(CacheMode::ReadOnly)) {
792-
if let Some(stats) = stats_arc {
793-
stats.write_failures.fetch_add(1, Ordering::Relaxed);
794-
}
780+
inc_stat!(stats_arc.as_deref(), write_failures, 1);
795781
return Err(anyhow!("Failed to write to cache level {}: {}", idx, e));
796782
}
797-
} else if let Some(stats) = stats_arc {
798-
stats.writes.fetch_add(1, Ordering::Relaxed);
799-
stats
800-
.write_duration_nanos
801-
.fetch_add(duration.as_nanos() as u64, Ordering::Relaxed);
783+
} else {
784+
inc_stat!(stats_arc.as_deref(), writes, 1);
785+
inc_stat!(
786+
stats_arc.as_deref(),
787+
write_duration_nanos,
788+
duration.as_nanos() as u64
789+
);
802790
}
803791
}
804792

0 commit comments

Comments
 (0)