xref: /aosp_15_r20/external/crosvm/crosvm_plugin/src/stats.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Instant;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use crate::Stat;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy)]
10*bb4ee6a4SAndroid Build Coastguard Worker struct StatEntry {
11*bb4ee6a4SAndroid Build Coastguard Worker     count: u64,
12*bb4ee6a4SAndroid Build Coastguard Worker     total: u64,
13*bb4ee6a4SAndroid Build Coastguard Worker     max: u64,
14*bb4ee6a4SAndroid Build Coastguard Worker }
15*bb4ee6a4SAndroid Build Coastguard Worker 
16*bb4ee6a4SAndroid Build Coastguard Worker pub struct StatUpdater {
17*bb4ee6a4SAndroid Build Coastguard Worker     idx: usize,
18*bb4ee6a4SAndroid Build Coastguard Worker     start: Instant,
19*bb4ee6a4SAndroid Build Coastguard Worker }
20*bb4ee6a4SAndroid Build Coastguard Worker 
21*bb4ee6a4SAndroid Build Coastguard Worker pub struct GlobalStats {
22*bb4ee6a4SAndroid Build Coastguard Worker     entries: [StatEntry; Stat::Count as usize],
23*bb4ee6a4SAndroid Build Coastguard Worker }
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker pub static mut STATS: GlobalStats = GlobalStats {
26*bb4ee6a4SAndroid Build Coastguard Worker     entries: [StatEntry {
27*bb4ee6a4SAndroid Build Coastguard Worker         count: 0,
28*bb4ee6a4SAndroid Build Coastguard Worker         total: 0,
29*bb4ee6a4SAndroid Build Coastguard Worker         max: 0,
30*bb4ee6a4SAndroid Build Coastguard Worker     }; Stat::Count as usize],
31*bb4ee6a4SAndroid Build Coastguard Worker };
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker impl GlobalStats {
34*bb4ee6a4SAndroid Build Coastguard Worker     // Record latency from this call until the end of block/function
35*bb4ee6a4SAndroid Build Coastguard Worker     // Example:
36*bb4ee6a4SAndroid Build Coastguard Worker     // pub fn foo() {
37*bb4ee6a4SAndroid Build Coastguard Worker     //     let _u = STATS.record(Stat::Foo);
38*bb4ee6a4SAndroid Build Coastguard Worker     //     // ... some operation ...
39*bb4ee6a4SAndroid Build Coastguard Worker     // }
40*bb4ee6a4SAndroid Build Coastguard Worker     // The added STATS.record will record latency of "some operation" and will
41*bb4ee6a4SAndroid Build Coastguard Worker     // update max and average latencies for it under Stats::Foo. Subsequent
42*bb4ee6a4SAndroid Build Coastguard Worker     // call to STATS.print() will print out max and average latencies for all
43*bb4ee6a4SAndroid Build Coastguard Worker     // operations that were performed.
record(&mut self, idx: Stat) -> StatUpdater44*bb4ee6a4SAndroid Build Coastguard Worker     pub fn record(&mut self, idx: Stat) -> StatUpdater {
45*bb4ee6a4SAndroid Build Coastguard Worker         StatUpdater {
46*bb4ee6a4SAndroid Build Coastguard Worker             idx: idx as usize,
47*bb4ee6a4SAndroid Build Coastguard Worker             start: Instant::now(),
48*bb4ee6a4SAndroid Build Coastguard Worker         }
49*bb4ee6a4SAndroid Build Coastguard Worker     }
50*bb4ee6a4SAndroid Build Coastguard Worker 
print(&self)51*bb4ee6a4SAndroid Build Coastguard Worker     pub fn print(&self) {
52*bb4ee6a4SAndroid Build Coastguard Worker         for idx in 0..Stat::Count as usize {
53*bb4ee6a4SAndroid Build Coastguard Worker             let e = &self.entries[idx as usize];
54*bb4ee6a4SAndroid Build Coastguard Worker             let stat = unsafe { std::mem::transmute::<u8, Stat>(idx as u8) };
55*bb4ee6a4SAndroid Build Coastguard Worker             if e.count > 0 {
56*bb4ee6a4SAndroid Build Coastguard Worker                 println!(
57*bb4ee6a4SAndroid Build Coastguard Worker                     "Stat::{:?}: avg {}ns max {}ns",
58*bb4ee6a4SAndroid Build Coastguard Worker                     stat,
59*bb4ee6a4SAndroid Build Coastguard Worker                     e.total / e.count,
60*bb4ee6a4SAndroid Build Coastguard Worker                     e.max
61*bb4ee6a4SAndroid Build Coastguard Worker                 );
62*bb4ee6a4SAndroid Build Coastguard Worker             }
63*bb4ee6a4SAndroid Build Coastguard Worker         }
64*bb4ee6a4SAndroid Build Coastguard Worker     }
65*bb4ee6a4SAndroid Build Coastguard Worker 
update(&mut self, idx: usize, elapsed_nanos: u64)66*bb4ee6a4SAndroid Build Coastguard Worker     fn update(&mut self, idx: usize, elapsed_nanos: u64) {
67*bb4ee6a4SAndroid Build Coastguard Worker         let e = &mut self.entries[idx as usize];
68*bb4ee6a4SAndroid Build Coastguard Worker         e.total += elapsed_nanos;
69*bb4ee6a4SAndroid Build Coastguard Worker         if e.max < elapsed_nanos {
70*bb4ee6a4SAndroid Build Coastguard Worker             e.max = elapsed_nanos;
71*bb4ee6a4SAndroid Build Coastguard Worker         }
72*bb4ee6a4SAndroid Build Coastguard Worker         e.count += 1;
73*bb4ee6a4SAndroid Build Coastguard Worker     }
74*bb4ee6a4SAndroid Build Coastguard Worker }
75*bb4ee6a4SAndroid Build Coastguard Worker 
76*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for StatUpdater {
drop(&mut self)77*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
78*bb4ee6a4SAndroid Build Coastguard Worker         let elapsed = self.start.elapsed();
79*bb4ee6a4SAndroid Build Coastguard Worker         let elapsed_nanos = elapsed.as_secs() * 1000000000 + elapsed.subsec_nanos() as u64;
80*bb4ee6a4SAndroid Build Coastguard Worker         // Unsafe due to racy access - OK for stats
81*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
82*bb4ee6a4SAndroid Build Coastguard Worker             STATS.update(self.idx, elapsed_nanos);
83*bb4ee6a4SAndroid Build Coastguard Worker         }
84*bb4ee6a4SAndroid Build Coastguard Worker     }
85*bb4ee6a4SAndroid Build Coastguard Worker }
86