use core::sync::atomic::{AtomicU64, Ordering};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(usize)]
pub enum Counter {
HistogramPass,
ResolveWalk,
CacheBitsBuild,
MatchHop,
MatchCompare,
OptimalDpStep,
ClusterScan,
ClusterEstimate,
PredictorModeEval,
CrossColorEval,
ColorCacheAlloc,
HistogramAlloc,
FdctCall,
QuantizeCall,
TrellisEval,
TokenCostWalk,
SseBlock,
PredictLuma,
PredictChroma,
MbComplexityFdct,
KmeansCompare,
ProbaOptNode,
TokenPartitionWalk,
BoolRead,
BoolRenorm,
CoeffToken,
IdctCall,
LoopFilterEdge,
UpsampleRow,
}
pub const N: usize = Counter::UpsampleRow as usize + 1;
#[allow(
clippy::declare_interior_mutable_const,
reason = "array-initializer seed for the static SLOTS array; never read through this const"
)]
const ZERO: AtomicU64 = AtomicU64::new(0);
static SLOTS: [AtomicU64; N] = [ZERO; N];
impl Counter {
#[inline]
pub fn bump(self) {
SLOTS[self as usize].fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn add(self, n: u64) {
SLOTS[self as usize].fetch_add(n, Ordering::Relaxed);
}
}
pub fn reset() {
for slot in &SLOTS {
slot.store(0, Ordering::Relaxed);
}
}
#[must_use]
pub fn snapshot() -> [u64; N] {
let mut out = [0u64; N];
for (dst, slot) in out.iter_mut().zip(SLOTS.iter()) {
*dst = slot.load(Ordering::Relaxed);
}
out
}
#[must_use]
pub const fn field_names() -> [&'static str; N] {
[
"histogram_pass",
"resolve_walk",
"cache_bits_build",
"match_hop",
"match_compare",
"optimal_dp_step",
"cluster_scan",
"cluster_estimate",
"predictor_mode_eval",
"cross_color_eval",
"color_cache_alloc",
"histogram_alloc",
"fdct_call",
"quantize_call",
"trellis_eval",
"token_cost_walk",
"sse_block",
"predict_luma",
"predict_chroma",
"mb_complexity_fdct",
"kmeans_compare",
"proba_opt_node",
"token_partition_walk",
"bool_read",
"bool_renorm",
"coeff_token",
"idct_call",
"loop_filter_edge",
"upsample_row",
]
}
#[cfg(test)]
mod tests {
use super::{Counter, N, field_names, reset, snapshot};
#[test]
fn field_names_align_with_slot_count() {
assert_eq!(field_names().len(), N);
}
#[test]
fn bump_add_and_reset_hit_the_right_slots() {
reset();
Counter::HistogramPass.bump();
Counter::HistogramPass.bump();
Counter::MatchCompare.add(40);
let snap = snapshot();
assert_eq!(snap[Counter::HistogramPass as usize], 2);
assert_eq!(snap[Counter::MatchCompare as usize], 40);
assert_eq!(snap[Counter::TokenPartitionWalk as usize], 0);
reset();
assert_eq!(snapshot(), [0u64; N]);
}
}