From a97b188beae979ec6faf77a5771c64a760df2cb7 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 11 Nov 2020 21:47:22 -0500 Subject: [PATCH] Make fps display and specification more precise --- Cargo.lock | 1 + chat-cli/src/main.rs | 2 +- common/Cargo.toml | 42 +++++++++++++++++++------------------ common/src/clock.rs | 29 +++++++++++++------------ server-cli/src/main.rs | 2 +- voxygen/src/main.rs | 4 +++- voxygen/src/run.rs | 4 ++-- voxygen/src/singleplayer.rs | 2 +- 8 files changed, 47 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index abf6abc16f..7e09b63623 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5140,6 +5140,7 @@ dependencies = [ "notify", "num-derive", "num-traits 0.2.12", + "ordered-float 2.0.0", "parking_lot 0.11.0", "rand 0.7.3", "rayon", diff --git a/chat-cli/src/main.rs b/chat-cli/src/main.rs index d537c42e75..485df26e6c 100644 --- a/chat-cli/src/main.rs +++ b/chat-cli/src/main.rs @@ -26,7 +26,7 @@ fn main() { info!("Starting chat-cli..."); // Set up an fps clock. - let mut clock = Clock::new(Duration::from_millis(1000 / TPS)); + let mut clock = Clock::new(Duration::from_secs_f64(1.0 / TPS as f64)); println!("Enter your username"); let username = read_input(); diff --git a/common/Cargo.toml b/common/Cargo.toml index 46eee67fae..26abab649b 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -13,34 +13,36 @@ default = ["simd"] [dependencies] arraygen = "0.1.13" -specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "specs-git" } - -roots = "0.0.6" -specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control"], rev = "7a2e348ab2223818bad487695c66c43db88050a5" } -vek = { version = "0.12.0", features = ["serde"] } +authc = { git = "https://gitlab.com/veloren/auth.git", rev = "b943c85e4a38f5ec60cd18c34c73097640162bfe" } +crossbeam = "0.7" directories-next = "2.0" dot_vox = "4.0" +enum-iterator = "0.6" +hashbrown = { version = "0.7.2", features = ["rayon", "serde", "nightly"] } image = { version = "0.23.8", default-features = false, features = ["png"] } +indexmap = "1.3.0" +lazy_static = "1.4.0" +notify = "5.0.0-pre.3" +num-derive = "0.3" +num-traits = "0.2" +ordered-float = { version = "2.0.0", default-features = false } +parking_lot = "0.11.0" +rand = "0.7" +rayon = "1.3.0" +ron = { version = "0.6", default-features = false } +roots = "0.0.6" serde = { version = "1.0.110", features = ["derive", "rc"] } serde_json = "1.0.50" serde_repr = "0.1.6" -ron = { version = "0.6", default-features = false } -tracing = { version = "0.1", default-features = false } -rand = "0.7" -rayon = "1.3.0" -lazy_static = "1.4.0" -hashbrown = { version = "0.7.2", features = ["rayon", "serde", "nightly"] } -parking_lot = "0.11.0" -crossbeam = "0.7" -notify = "5.0.0-pre.3" -indexmap = "1.3.0" -sum_type = "0.2.0" -authc = { git = "https://gitlab.com/veloren/auth.git", rev = "b943c85e4a38f5ec60cd18c34c73097640162bfe" } slab = "0.4.2" -enum-iterator = "0.6" spin_sleep = "1.0" -num-traits = "0.2" -num-derive = "0.3" +sum_type = "0.2.0" +tracing = { version = "0.1", default-features = false } +vek = { version = "0.12.0", features = ["serde"] } + +# ECS +specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control"], rev = "7a2e348ab2223818bad487695c66c43db88050a5" } +specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "specs-git" } # Tracy tracy-client = { version = "0.9.0", optional = true } diff --git a/common/src/clock.rs b/common/src/clock.rs index bcdf398f8c..1e2119c162 100644 --- a/common/src/clock.rs +++ b/common/src/clock.rs @@ -1,4 +1,5 @@ use crate::span; +use ordered_float::NotNan; use std::{ collections::VecDeque, time::{Duration, Instant}, @@ -26,10 +27,9 @@ pub struct Clock { /// summed up `last_dt` total_tick_time: Duration, // Stats only - // stored as millis in u16 to save space. if it's more than u16::MAX (16s) we have other - // problems - last_dts_millis: VecDeque, - last_dts_millis_sorted: Vec, + // uses f32 so we have enough precision to display fps values while saving space + last_dts_millis: VecDeque>, + last_dts_millis_sorted: Vec>, stats: ClockStats, } @@ -74,13 +74,14 @@ impl Clock { /// Do not modify without asking @xMAC94x first! pub fn tick(&mut self) { span!(_guard, "tick", "Clock::tick"); + span!(guard, "clock work"); let current_sys_time = Instant::now(); let busy_delta = current_sys_time.duration_since(self.last_sys_time); // Maintain TPS self.last_dts_millis_sorted = self.last_dts_millis.iter().copied().collect(); self.last_dts_millis_sorted.sort_unstable(); self.stats = ClockStats::new(&self.last_dts_millis_sorted, busy_delta); - + drop(guard); // Attempt to sleep to fill the gap. if let Some(sleep_dur) = self.target_dt.checked_sub(busy_delta) { spin_sleep::sleep(sleep_dur); @@ -91,29 +92,31 @@ impl Clock { if self.last_dts_millis.len() >= NUMBER_OF_OLD_DELTAS_KEPT { self.last_dts_millis.pop_front(); } - self.last_dts_millis - .push_back((self.last_dt.as_millis() as u16).min(std::u16::MAX)); + self.last_dts_millis.push_back( + NotNan::new(self.last_dt.as_secs_f32() * 1000.0) + .expect("Duration::as_secs_f32 never returns NaN"), + ); self.total_tick_time += self.last_dt; self.last_sys_time = after_sleep_sys_time; } } impl ClockStats { - fn new(sorted: &[u16], last_busy_dt: Duration) -> Self { + fn new(sorted: &[NotNan], last_busy_dt: Duration) -> Self { const NANOS_PER_SEC: f64 = Duration::from_secs(1).as_nanos() as f64; const NANOS_PER_MILLI: f64 = Duration::from_millis(1).as_nanos() as f64; let len = sorted.len(); - let average_millis = sorted.iter().fold(0, |a, x| a + *x as u32) / len.max(1) as u32; + let average_millis = sorted.iter().sum::>().into_inner() / len.max(1) as f32; let average_tps = NANOS_PER_SEC / (average_millis as f64 * NANOS_PER_MILLI); let (median_tps, percentile_90_tps, percentile_95_tps, percentile_99_tps) = if len >= NUMBER_OF_OLD_DELTAS_KEPT { - let median_millis = sorted[len / 2]; - let percentile_90_millis = sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.1) as usize]; - let percentile_95_millis = sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.05) as usize]; - let percentile_99_millis = sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.01) as usize]; + let median_millis = *sorted[len / 2]; + let percentile_90_millis = *sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.1) as usize]; + let percentile_95_millis = *sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.05) as usize]; + let percentile_99_millis = *sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.01) as usize]; let median_tps = NANOS_PER_SEC / (median_millis as f64 * NANOS_PER_MILLI); let percentile_90_tps = NANOS_PER_SEC / (percentile_90_millis as f64 * NANOS_PER_MILLI); diff --git a/server-cli/src/main.rs b/server-cli/src/main.rs index e5a52a8648..307088b517 100644 --- a/server-cli/src/main.rs +++ b/server-cli/src/main.rs @@ -140,7 +140,7 @@ fn main() -> io::Result<()> { let mut shutdown_coordinator = ShutdownCoordinator::new(Arc::clone(&sigusr1_signal)); // Set up an fps clock - let mut clock = Clock::new(Duration::from_millis(1000 / TPS)); + let mut clock = Clock::new(Duration::from_secs_f64(1.0 / TPS as f64)); // Wait for a tick so we don't start with a zero dt loop { diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index f87b32d35b..8fe5867110 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -184,8 +184,10 @@ fn main() { audio, profile, window, + clock: Clock::new(std::time::Duration::from_secs_f64( + 1.0 / settings.graphics.max_fps as f64, + )), settings, - clock: Clock::new(std::time::Duration::from_millis(30)), info_message: None, #[cfg(feature = "singleplayer")] singleplayer: None, diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index 1c75aced18..de176655f1 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -178,8 +178,8 @@ fn handle_main_events_cleared( if !exit { // Wait for the next tick. span!(_guard, "Main thread sleep"); - global_state.clock.set_target_dt(Duration::from_millis( - 1000 / global_state.settings.graphics.max_fps as u64, + global_state.clock.set_target_dt(Duration::from_secs_f64( + 1.0 / global_state.settings.graphics.max_fps as f64, )); global_state.clock.tick(); diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs index 0bc68f50d9..0e1a050988 100644 --- a/voxygen/src/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -152,7 +152,7 @@ fn run_server(mut server: Server, rec: Receiver, paused: Arc) { info!("Starting server-cli..."); // Set up an fps clock - let mut clock = Clock::new(Duration::from_millis(1000 / TPS)); + let mut clock = Clock::new(Duration::from_secs_f64(1.0 / TPS as f64)); loop { // Check any event such as stopping and pausing