aboutsummaryrefslogtreecommitdiff
path: root/src/meter.rs
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-05-21 11:08:50 -0700
committerJoe Wilm <joe@jwilm.com>2016-05-21 11:08:50 -0700
commit855ae756973990be35186d554562a75f692c06e7 (patch)
tree82506bd1a0e75cf3d04cac86e0043fcc0dd6ba8f /src/meter.rs
parentc70acbac0b721ea2f1b1442898c22aee0f360ef2 (diff)
downloadalacritty-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.rs104
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;
+ }
+}