blob: 320f5456aa7ff36f3b608c2d814361d3da00ccc2 [file] [log] [blame]
// Copyright 2021 The Fuchsia 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 fuchsia_zircon as zx;
// This mod implements a refresh rate counter that calculates the exponential moving average of the
// frame rate. See https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average.
const ALPHA: f32 = 0.6;
pub(crate) struct Counter {
// Most recent frame timestamp
last_sample_timestamp: zx::Time,
// Stores the exponential moving average of the time between two frames, using the above
// `ALPHA` as the weight.
avg_time_delta_ns: f32,
// Total number of frames
num_frames: i64,
}
pub(crate) struct Counts {
pub sample_rate_hz: f32,
pub sample_time_delta_ms: f32,
pub num_frames: i64,
}
impl Counter {
pub fn new() -> Counter {
Counter {
last_sample_timestamp: zx::Time::get_monotonic(),
avg_time_delta_ns: 0.0,
num_frames: 0,
}
}
pub fn add(&mut self, timestamp: zx::Time) {
let delta = timestamp - self.last_sample_timestamp;
self.last_sample_timestamp = timestamp;
let delta = delta.into_nanos() as f32;
// This is arithmetically equivalent to:
// ALPHA * delta + (1 - ALPHA) * self.avg_time_delta_ns
self.avg_time_delta_ns += ALPHA * (delta - self.avg_time_delta_ns);
self.num_frames += 1;
}
pub fn stats(&self) -> Counts {
Counts {
sample_rate_hz: 1000000000f32 / self.avg_time_delta_ns,
sample_time_delta_ms: self.avg_time_delta_ns / 1000000f32,
num_frames: self.num_frames,
}
}
}