mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-06 03:15:48 -06:00
fix: avoid padding jitter with constant name padding, minor timing calculation fixes
This commit is contained in:
@@ -89,7 +89,7 @@ impl App {
|
||||
let start = Instant::now();
|
||||
|
||||
let dt = self.last_tick.elapsed().as_secs_f32();
|
||||
self.last_tick = Instant::now();
|
||||
self.last_tick = start;
|
||||
|
||||
let exit = self.game.tick(dt);
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ use glam::UVec2;
|
||||
///
|
||||
/// Calculated as 1/60th of a second (≈16.67ms).
|
||||
///
|
||||
/// Written out explicitly to satisfy const-eval constraints.
|
||||
pub const LOOP_TIME: Duration = Duration::from_nanos((1_000_000_000.0 / 60.0) as u64);
|
||||
/// Uses integer arithmetic to avoid floating-point precision loss.
|
||||
pub const LOOP_TIME: Duration = Duration::from_nanos(1_000_000_000 / 60);
|
||||
|
||||
/// The size of each cell, in pixels.
|
||||
pub const CELL_SIZE: u32 = 8;
|
||||
|
||||
@@ -138,14 +138,12 @@ pub fn input_system(
|
||||
|
||||
// Warn if the smallvec was heap allocated due to exceeding stack capacity
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if frame_events.len() > frame_events.capacity() {
|
||||
tracing::warn!(
|
||||
"More than {} events in a frame, consider adjusting stack capacity: {:?}",
|
||||
frame_events.capacity(),
|
||||
frame_events
|
||||
);
|
||||
}
|
||||
if frame_events.len() > frame_events.capacity() {
|
||||
tracing::warn!(
|
||||
"More than {} events in a frame, consider adjusting stack capacity: {:?}",
|
||||
frame_events.capacity(),
|
||||
frame_events
|
||||
);
|
||||
}
|
||||
|
||||
// Handle non-keyboard events inline and build a simplified keyboard event stream.
|
||||
|
||||
@@ -7,8 +7,8 @@ use parking_lot::{Mutex, RwLock};
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt::Display;
|
||||
use std::time::Duration;
|
||||
use strum::EnumCount;
|
||||
use strum_macros::{EnumCount, IntoStaticStr};
|
||||
use strum::{EnumCount, IntoEnumIterator};
|
||||
use strum_macros::{EnumCount, EnumIter, IntoStaticStr};
|
||||
use thousands::Separable;
|
||||
|
||||
/// The maximum number of systems that can be profiled. Must not be exceeded, or it will panic.
|
||||
@@ -16,7 +16,7 @@ const MAX_SYSTEMS: usize = SystemId::COUNT;
|
||||
/// The number of durations to keep in the circular buffer.
|
||||
const TIMING_WINDOW_SIZE: usize = 30;
|
||||
|
||||
#[derive(EnumCount, IntoStaticStr, Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||
#[derive(EnumCount, EnumIter, IntoStaticStr, Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||
pub enum SystemId {
|
||||
Input,
|
||||
PlayerControls,
|
||||
@@ -96,7 +96,7 @@ impl SystemTimings {
|
||||
let sum: f64 = durations.iter().sum();
|
||||
let mean = sum / count;
|
||||
|
||||
let variance = durations.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / count;
|
||||
let variance = durations.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / (count - 1.0).max(1.0);
|
||||
let std_dev = variance.sqrt();
|
||||
|
||||
stats.insert(
|
||||
@@ -128,7 +128,7 @@ impl SystemTimings {
|
||||
diff_secs * diff_secs
|
||||
})
|
||||
.sum::<f64>()
|
||||
/ duration_sums.len() as f64;
|
||||
/ (duration_sums.len() - 1).max(1) as f64;
|
||||
let std_dev_secs = variance.sqrt();
|
||||
|
||||
(mean, Duration::from_secs_f64(std_dev_secs))
|
||||
@@ -250,17 +250,22 @@ pub fn format_timing_display(
|
||||
})
|
||||
.collect::<SmallVec<[Entry; 12]>>();
|
||||
|
||||
let (max_name_width, max_avg_int_width, max_avg_decimal_width, max_std_int_width, max_std_decimal_width) = entries
|
||||
.iter()
|
||||
.fold((0, 0, 3, 0, 3), |(name_w, avg_int_w, avg_dec_w, std_int_w, std_dec_w), e| {
|
||||
(
|
||||
name_w.max(e.name.len()),
|
||||
avg_int_w.max(e.avg_int.width() as usize),
|
||||
avg_dec_w.max(e.avg_decimal.width() as usize),
|
||||
std_int_w.max(e.std_int.width() as usize),
|
||||
std_dec_w.max(e.std_decimal.width() as usize),
|
||||
)
|
||||
});
|
||||
let (max_avg_int_width, max_avg_decimal_width, max_std_int_width, max_std_decimal_width) =
|
||||
entries
|
||||
.iter()
|
||||
.fold((0, 3, 0, 3), |(avg_int_w, avg_dec_w, std_int_w, std_dec_w), e| {
|
||||
(
|
||||
avg_int_w.max(e.avg_int.width() as usize),
|
||||
avg_dec_w.max(e.avg_decimal.width() as usize),
|
||||
std_int_w.max(e.std_int.width() as usize),
|
||||
std_dec_w.max(e.std_decimal.width() as usize),
|
||||
)
|
||||
});
|
||||
|
||||
let max_name_width = SystemId::iter()
|
||||
.map(|id| id.to_string().len())
|
||||
.max()
|
||||
.expect("SystemId::iter() returned an empty iterator");
|
||||
|
||||
entries.iter().map(|e| {
|
||||
format!(
|
||||
|
||||
@@ -14,6 +14,7 @@ fn test_timing_statistics() {
|
||||
timings.add_timing(SystemId::Blinking, Duration::from_millis(3));
|
||||
timings.add_timing(SystemId::Blinking, Duration::from_millis(2));
|
||||
timings.add_timing(SystemId::Blinking, Duration::from_millis(1));
|
||||
|
||||
fn close_enough(a: Duration, b: Duration) -> bool {
|
||||
if a > b {
|
||||
a - b < Duration::from_micros(500) // 0.1ms
|
||||
@@ -36,25 +37,8 @@ fn test_timing_statistics() {
|
||||
total_avg
|
||||
);
|
||||
assert!(
|
||||
close_enough(total_std, Duration::from_millis(12)),
|
||||
close_enough(total_std, Duration::from_millis(17)),
|
||||
"total_std: {:?}",
|
||||
total_std
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_window_size_limit() {
|
||||
// let timings = SystemTimings::default();
|
||||
|
||||
// // Add more than 90 timings to test window size limit
|
||||
// for i in 0..100 {
|
||||
// timings.add_timing("test_system", Duration::from_millis(i));
|
||||
// }
|
||||
|
||||
// let stats = timings.get_stats();
|
||||
// let (avg, _) = stats.get("test_system").unwrap();
|
||||
|
||||
// // Should only keep the last 90 values, so average should be around 55ms
|
||||
// // (average of 10-99)
|
||||
// assert!((avg.as_millis() as f64 - 55.0).abs() < 5.0);
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user