// Copyright 2016 Joe Wilm, The Alacritty Project Contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //! Rendering time meter //! //! Used to track rendering times and provide moving averages. //! //! # Examples //! //! ```rust //! // create a meter //! let mut meter = alacritty::meter::Meter::new(); //! //! // Sample something. //! { //! let _sampler = meter.sampler(); //! } //! //! // Get the moving average. The meter tracks a fixed number of samples, and //! // the average won't mean much until it's filled up at least once. //! println!("Average time: {}", meter.average()); use std::time::{Instant, Duration}; const NUM_SAMPLES: usize = 10; /// The meter #[derive(Default)] 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, 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 { Default::default() } /// 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 += f64::from(sample.subsec_nanos()) / 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; } }