diff options
Diffstat (limited to 'crosvm_plugin/src/stats.rs')
-rw-r--r-- | crosvm_plugin/src/stats.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/crosvm_plugin/src/stats.rs b/crosvm_plugin/src/stats.rs new file mode 100644 index 0000000..0406e2f --- /dev/null +++ b/crosvm_plugin/src/stats.rs @@ -0,0 +1,84 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use crate::Stat; +use std::time::Instant; + +#[derive(Clone, Copy)] +struct StatEntry { + count: u64, + total: u64, + max: u64, +} + +pub struct StatUpdater { + idx: usize, + start: Instant, +} + +pub struct GlobalStats { + entries: [StatEntry; Stat::Count as usize], +} + +pub static mut STATS: GlobalStats = GlobalStats { + entries: [StatEntry { + count: 0, + total: 0, + max: 0, + }; Stat::Count as usize], +}; + +impl GlobalStats { + // Record latency from this call until the end of block/function + // Example: + // pub fn foo() { + // let _u = STATS.record(Stat::Foo); + // // ... some operation ... + // } + // The added STATS.record will record latency of "some operation" and will + // update max and average latencies for it under Stats::Foo. Subsequent + // call to STATS.print() will print out max and average latencies for all + // operations that were performed. + pub fn record(&mut self, idx: Stat) -> StatUpdater { + StatUpdater { + idx: idx as usize, + start: Instant::now(), + } + } + + pub fn print(&self) { + for idx in 0..Stat::Count as usize { + let e = &self.entries[idx as usize]; + let stat = unsafe { std::mem::transmute::<u8, Stat>(idx as u8) }; + if e.count > 0 { + println!( + "Stat::{:?}: avg {}ns max {}ns", + stat, + e.total / e.count, + e.max + ); + } + } + } + + fn update(&mut self, idx: usize, elapsed_nanos: u64) { + let e = &mut self.entries[idx as usize]; + e.total += elapsed_nanos; + if e.max < elapsed_nanos { + e.max = elapsed_nanos; + } + e.count += 1; + } +} + +impl Drop for StatUpdater { + fn drop(&mut self) { + let elapsed = self.start.elapsed(); + let elapsed_nanos = elapsed.as_secs() * 1000000000 + elapsed.subsec_nanos() as u64; + // Unsafe due to racy access - OK for stats + unsafe { + STATS.update(self.idx, elapsed_nanos); + } + } +} |