qualia_core_db/inference/inference_bench/
metrics.rs1use std::sync::atomic::{AtomicU64, Ordering};
8use std::time::Duration;
9
10use serde::Serialize;
11
12static LOAD_NS: AtomicU64 = AtomicU64::new(0);
18static PREFILL_NS: AtomicU64 = AtomicU64::new(0);
19static PREFILL_TOKENS: AtomicU64 = AtomicU64::new(0);
20static DECODE_NS: AtomicU64 = AtomicU64::new(0);
21static DECODE_TOKENS: AtomicU64 = AtomicU64::new(0);
22static DECODE_FORWARD_NS: AtomicU64 = AtomicU64::new(0);
26static DECODE_OUTPUT_NS: AtomicU64 = AtomicU64::new(0);
27static DECODE_EMPTY_RT_NS: AtomicU64 = AtomicU64::new(0);
30static DECODE_EMPTY_RT_N: AtomicU64 = AtomicU64::new(0);
31
32#[inline]
34pub fn record_empty_rt(total_ns: u64, n: u64) {
35 DECODE_EMPTY_RT_NS.store(total_ns, Ordering::Relaxed);
36 DECODE_EMPTY_RT_N.store(n, Ordering::Relaxed);
37}
38#[inline]
40pub fn empty_rt() -> (u64, u64) {
41 (
42 DECODE_EMPTY_RT_NS.load(Ordering::Relaxed),
43 DECODE_EMPTY_RT_N.load(Ordering::Relaxed),
44 )
45}
46
47#[inline]
49pub fn gpu_wait_count() -> u64 {
50 crate::gguf_bridge::gpu_wait_count()
51}
52
53#[inline]
55pub fn add_decode_forward_ns(ns: u64) {
56 DECODE_FORWARD_NS.fetch_add(ns, Ordering::Relaxed);
57}
58#[inline]
60pub fn add_decode_output_ns(ns: u64) {
61 DECODE_OUTPUT_NS.fetch_add(ns, Ordering::Relaxed);
62}
63static DECODE_ATTN_NS: AtomicU64 = AtomicU64::new(0);
66static DECODE_FFN_NS: AtomicU64 = AtomicU64::new(0);
67#[inline]
69pub fn add_decode_attn_ns(ns: u64) {
70 DECODE_ATTN_NS.fetch_add(ns, Ordering::Relaxed);
71}
72#[inline]
74pub fn add_decode_ffn_ns(ns: u64) {
75 DECODE_FFN_NS.fetch_add(ns, Ordering::Relaxed);
76}
77#[inline]
79pub fn decode_attn_ffn() -> (u64, u64) {
80 (
81 DECODE_ATTN_NS.load(Ordering::Relaxed),
82 DECODE_FFN_NS.load(Ordering::Relaxed),
83 )
84}
85
86#[inline]
88pub fn reset_phase_metrics() {
89 LOAD_NS.store(0, Ordering::Relaxed);
90 PREFILL_NS.store(0, Ordering::Relaxed);
91 PREFILL_TOKENS.store(0, Ordering::Relaxed);
92 DECODE_NS.store(0, Ordering::Relaxed);
93 DECODE_TOKENS.store(0, Ordering::Relaxed);
94 DECODE_FORWARD_NS.store(0, Ordering::Relaxed);
95 DECODE_OUTPUT_NS.store(0, Ordering::Relaxed);
96 DECODE_ATTN_NS.store(0, Ordering::Relaxed);
97 DECODE_FFN_NS.store(0, Ordering::Relaxed);
98 DECODE_EMPTY_RT_NS.store(0, Ordering::Relaxed);
99 DECODE_EMPTY_RT_N.store(0, Ordering::Relaxed);
100 crate::gguf_bridge::reset_gpu_wait_count();
101}
102
103#[inline]
105pub fn record_load_ns(ns: u64) {
106 LOAD_NS.store(ns, Ordering::Relaxed);
107}
108
109#[inline]
111pub fn record_prefill(ns: u64, tokens: u64) {
112 PREFILL_NS.store(ns, Ordering::Relaxed);
113 PREFILL_TOKENS.store(tokens, Ordering::Relaxed);
114}
115
116#[inline]
118pub fn record_decode(ns: u64, tokens: u64) {
119 DECODE_NS.store(ns, Ordering::Relaxed);
120 DECODE_TOKENS.store(tokens, Ordering::Relaxed);
121}
122
123#[derive(Debug, Clone, Copy, Serialize)]
125pub struct LlmPhaseSnapshot {
126 pub load_ns: u64,
127 pub prefill_ns: u64,
128 pub prefill_tokens: u64,
129 pub decode_ns: u64,
130 pub decode_tokens: u64,
131 pub decode_forward_ns: u64,
132 pub decode_output_ns: u64,
133}
134
135#[inline]
137pub fn phase_snapshot() -> LlmPhaseSnapshot {
138 LlmPhaseSnapshot {
139 load_ns: LOAD_NS.load(Ordering::Relaxed),
140 prefill_ns: PREFILL_NS.load(Ordering::Relaxed),
141 prefill_tokens: PREFILL_TOKENS.load(Ordering::Relaxed),
142 decode_ns: DECODE_NS.load(Ordering::Relaxed),
143 decode_tokens: DECODE_TOKENS.load(Ordering::Relaxed),
144 decode_forward_ns: DECODE_FORWARD_NS.load(Ordering::Relaxed),
145 decode_output_ns: DECODE_OUTPUT_NS.load(Ordering::Relaxed),
146 }
147}
148
149#[inline]
155pub(super) fn ms(d: Duration) -> f64 {
156 d.as_secs_f64() * 1000.0
157}
158
159#[inline]
160pub(super) fn ns_to_ms(ns: u64) -> f64 {
161 ns as f64 / 1_000_000.0
162}
163
164#[inline]
165pub(super) fn tok_per_s(tokens: u64, ns: u64) -> f64 {
166 if ns == 0 || tokens == 0 {
167 0.0
168 } else {
169 tokens as f64 / (ns as f64 / 1_000_000_000.0)
170 }
171}