use std::sync::atomic::{AtomicU64, Ordering};
use serde::{Deserialize, Serialize};
static PROSE_SEGMENTS: AtomicU64 = AtomicU64::new(0);
static PROSE_REQUESTS: AtomicU64 = AtomicU64::new(0);
static CACHE_SAFE_REQUESTS: AtomicU64 = AtomicU64::new(0);
static COLD_PREFIX_REPACKS: AtomicU64 = AtomicU64::new(0);
static BREAKPOINTS_INJECTED: AtomicU64 = AtomicU64::new(0);
static VOLATILE_SYSTEM_REQUESTS: AtomicU64 = AtomicU64::new(0);
static VOLATILE_FIELDS_DETECTED: AtomicU64 = AtomicU64::new(0);
pub fn record(segments: u64, all_safe: bool) {
if segments == 0 {
return;
}
PROSE_SEGMENTS.fetch_add(segments, Ordering::Relaxed);
PROSE_REQUESTS.fetch_add(1, Ordering::Relaxed);
if all_safe {
CACHE_SAFE_REQUESTS.fetch_add(1, Ordering::Relaxed);
}
}
pub fn record_cold_repack() {
COLD_PREFIX_REPACKS.fetch_add(1, Ordering::Relaxed);
}
pub fn record_breakpoint_injected() {
BREAKPOINTS_INJECTED.fetch_add(1, Ordering::Relaxed);
}
pub fn record_volatile_system(fields: u64) {
if fields == 0 {
return;
}
VOLATILE_SYSTEM_REQUESTS.fetch_add(1, Ordering::Relaxed);
VOLATILE_FIELDS_DETECTED.fetch_add(fields, Ordering::Relaxed);
}
#[must_use]
pub fn ratio(safe: u64, total: u64) -> f64 {
if total == 0 {
return 1.0;
}
safe as f64 / total as f64
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
pub struct CacheSafety {
pub prose_segments_compressed: u64,
pub prose_requests: u64,
pub cache_safe_ratio: f64,
#[serde(default)]
pub cold_prefix_repacks: u64,
#[serde(default)]
pub breakpoints_injected: u64,
#[serde(default)]
pub volatile_system_requests: u64,
#[serde(default)]
pub volatile_fields_detected: u64,
}
#[must_use]
pub fn snapshot() -> CacheSafety {
let prose_requests = PROSE_REQUESTS.load(Ordering::Relaxed);
let safe = CACHE_SAFE_REQUESTS.load(Ordering::Relaxed);
CacheSafety {
prose_segments_compressed: PROSE_SEGMENTS.load(Ordering::Relaxed),
prose_requests,
cache_safe_ratio: ratio(safe, prose_requests),
cold_prefix_repacks: COLD_PREFIX_REPACKS.load(Ordering::Relaxed),
breakpoints_injected: BREAKPOINTS_INJECTED.load(Ordering::Relaxed),
volatile_system_requests: VOLATILE_SYSTEM_REQUESTS.load(Ordering::Relaxed),
volatile_fields_detected: VOLATILE_FIELDS_DETECTED.load(Ordering::Relaxed),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ratio_is_one_when_empty() {
assert_eq!(ratio(0, 0), 1.0);
}
#[test]
fn ratio_reflects_unsafe_rewrites() {
assert_eq!(ratio(3, 3), 1.0);
assert_eq!(ratio(2, 4), 0.5);
assert_eq!(ratio(0, 2), 0.0);
}
}