diff options
author | Joe Wilm <joe@jwilm.com> | 2016-05-21 11:08:50 -0700 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-05-21 11:08:50 -0700 |
commit | 855ae756973990be35186d554562a75f692c06e7 (patch) | |
tree | 82506bd1a0e75cf3d04cac86e0043fcc0dd6ba8f /src/meter.rs | |
parent | c70acbac0b721ea2f1b1442898c22aee0f360ef2 (diff) | |
download | alacritty-855ae756973990be35186d554562a75f692c06e7.tar.gz alacritty-855ae756973990be35186d554562a75f692c06e7.zip |
Add render time meter
Optimization is impossible without measurement!
Diffstat (limited to 'src/meter.rs')
-rw-r--r-- | src/meter.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/meter.rs b/src/meter.rs new file mode 100644 index 00000000..3badf330 --- /dev/null +++ b/src/meter.rs @@ -0,0 +1,104 @@ +//! Rendering time meter +//! +//! Used to track rendering times and provide moving averages. +//! +//! # Examples +//! +//! ```rust +//! // create a meter +//! let mut meter = Meter::new(); +//! +//! // Sample something. +//! { +//! let _sampler = meter.sampler(); +//! } +//! +//! // Get the moving average. The meter tracks a fixed number of samles, and the average won't mean +//! // much until it's filled up at least once. +//! printf!("Average time: {}", meter.average()); + +use std::time::{Instant, Duration}; + +const NUM_SAMPLES: usize = 60; + +/// The meter +pub struct Meter { + /// Track last 60 timestamps + times: [f64; NUM_SAMPLES], + + /// Average sample time in microseconds + avg: f64, + + /// Index of next time to update. + index: usize, +} + +/// Sampler +/// +/// Samplers record how long they are "alive" for and update the meter on drop. +pub struct Sampler<'a> { + /// Reference to meter that created the sampler + meter: &'a mut Meter, + + // When the sampler was created + created_at: Instant, +} + +impl<'a> Sampler<'a> { + fn new(meter: &'a mut Meter) -> Sampler<'a> { + Sampler { + meter: meter, + created_at: Instant::now(), + } + } + + #[inline] + fn alive_duration(&self) -> Duration { + self.created_at.elapsed() + } +} + +impl<'a> Drop for Sampler<'a> { + fn drop(&mut self) { + // Work around borrowck + let duration = self.alive_duration(); + self.meter.add_sample(duration); + } +} + +impl Meter { + /// Create a meter + pub fn new() -> Meter { + Meter { + times: [0.0; NUM_SAMPLES], + avg: 0.0, + index: 0, + } + } + + /// Get a sampler + pub fn sampler(&mut self) -> Sampler { + Sampler::new(self) + } + + /// Get the current average sample duration in microseconds + pub fn average(&self) -> f64 { + self.avg + } + + /// Add a sample + /// + /// Used by Sampler::drop. + fn add_sample(&mut self, sample: Duration) { + let mut usec = 0f64; + + usec += (sample.subsec_nanos() as f64) / 1e3; + usec += (sample.as_secs() as f64) * 1e6; + + let prev = self.times[self.index]; + self.times[self.index] = usec; + self.avg -= prev / NUM_SAMPLES as f64; + self.avg += usec / NUM_SAMPLES as f64; + self.index = (self.index + 1) % NUM_SAMPLES; + } +} |