From 69d019e5ac8c5002b9ec4195998d906cbcbf980b Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 11 Nov 2020 21:47:22 -0500 Subject: [PATCH 1/4] 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 From 73c0a7a7513679cf55764e2532248d8faaf4afe1 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 11 Nov 2020 22:33:02 -0500 Subject: [PATCH 2/4] Add tracy feature that randomly disappeared back into voxygen --- Cargo.lock | 1 + voxygen/Cargo.toml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 7e09b63623..bd04e29ddc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5264,6 +5264,7 @@ dependencies = [ "tracing-appender", "tracing-log", "tracing-subscriber", + "tracing-tracy", "treeculler", "uvth 3.1.1", "vek 0.12.0", diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 57ac5addc4..4b69213961 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -14,6 +14,7 @@ hot-anim = ["anim/use-dyn-lib"] singleplayer = ["server"] tweak = ["const-tweaker"] simd = ["vek/platform_intrinsics"] +tracy = ["tracing-tracy", "common/tracy"] default = ["gl", "singleplayer", "native-dialog", "simd"] @@ -84,6 +85,9 @@ const-tweaker = {version = "0.3.1", optional = true} inline_tweak = "1.0.2" itertools = "0.9.0" +# Tracy +tracing-tracy = { version = "0.3.0", optional = true } + # Logging tracing = "0.1" tracing-appender = "0.1" From ebaa35ea7923e73bcf7fb5b9a3a437982cdafbc8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 11 Nov 2020 23:26:13 -0500 Subject: [PATCH 3/4] Display averaged busy dt --- common/src/clock.rs | 33 +++++++++++++++++++++++---------- voxygen/src/session.rs | 2 +- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/common/src/clock.rs b/common/src/clock.rs index 1e2119c162..3299a804b8 100644 --- a/common/src/clock.rs +++ b/common/src/clock.rs @@ -19,25 +19,28 @@ use std::{ pub struct Clock { /// This is the dt that the Clock tries to archive with each call of tick. target_dt: Duration, - /// last time `tick` was called + /// Last time `tick` was called last_sys_time: Instant, - /// will be calculated in `tick` returns the dt used by the next iteration + /// Will be calculated in `tick` returns the dt used by the next iteration /// of the main loop last_dt: Duration, - /// summed up `last_dt` + /// Summed up `last_dt` total_tick_time: Duration, // Stats only // uses f32 so we have enough precision to display fps values while saving space last_dts_millis: VecDeque>, last_dts_millis_sorted: Vec>, + // Seconds + last_busy_dts: VecDeque>, stats: ClockStats, } pub struct ClockStats { - /// busy_dt is the part of the last tick that we didn't sleep. + /// Busy dt is the part of the tick that we didn't sleep. /// e.g. the total tick is 33ms, including 25ms sleeping. then this returns /// 8ms - pub last_busy_dt: Duration, + /// This is in seconds + pub average_busy_dt: f32, /// avg over the last NUMBER_OF_OLD_DELTAS_KEPT ticks pub average_tps: f64, /// = 50% percentile @@ -61,7 +64,8 @@ impl Clock { total_tick_time: Duration::default(), last_dts_millis: VecDeque::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), last_dts_millis_sorted: Vec::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), - stats: ClockStats::new(&Vec::new(), target_dt), + last_busy_dts: VecDeque::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), + stats: ClockStats::new(&[], &VecDeque::new()), } } @@ -80,7 +84,7 @@ impl Clock { // 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); + self.stats = ClockStats::new(&self.last_dts_millis_sorted, &self.last_busy_dts); drop(guard); // Attempt to sleep to fill the gap. if let Some(sleep_dur) = self.target_dt.checked_sub(busy_delta) { @@ -92,23 +96,32 @@ impl Clock { if self.last_dts_millis.len() >= NUMBER_OF_OLD_DELTAS_KEPT { self.last_dts_millis.pop_front(); } + if self.last_busy_dts.len() >= NUMBER_OF_OLD_DELTAS_KEPT { + self.last_busy_dts.pop_front(); + } 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.last_busy_dts.push_back( + NotNan::new(busy_delta.as_secs_f32()).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: &[NotNan], last_busy_dt: Duration) -> Self { + fn new(sorted: &[NotNan], busy_dt_list: &VecDeque>) -> 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().sum::>().into_inner() / len.max(1) as f32; + let average_busy_dt = busy_dt_list.iter().sum::>().into_inner() + / busy_dt_list.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 @@ -129,12 +142,12 @@ impl ClockStats { percentile_99_tps, ) } else { - let avg_tps = NANOS_PER_SEC / last_busy_dt.as_nanos() as f64; + let avg_tps = 1.0 / average_busy_dt as f64; (avg_tps, avg_tps, avg_tps, avg_tps) }; Self { - last_busy_dt, + average_busy_dt, average_tps, median_tps, percentile_90_tps, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 0a5f8e5503..d1987291ee 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -694,7 +694,7 @@ impl PlayState for SessionState { .toggle_debug .then(|| DebugInfo { tps: global_state.clock.stats().average_tps, - frame_time: global_state.clock.stats().last_busy_dt, + frame_time: Duration::from_secs_f32(global_state.clock.stats().average_busy_dt), ping_ms: self.client.borrow().get_ping_ms_rolling_avg(), coordinates: self .client From 2dfebb897836402a20a4a473c7f5151793fc3a69 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 12 Nov 2020 19:17:30 -0500 Subject: [PATCH 4/4] Add more catagories to common deps, store average busy dt as a duration, store frame delta times as seconds instead of milliseconds --- common/Cargo.toml | 32 ++++++++++------- common/src/clock.rs | 81 +++++++++++++++++++++--------------------- voxygen/src/session.rs | 2 +- 3 files changed, 61 insertions(+), 54 deletions(-) diff --git a/common/Cargo.toml b/common/Cargo.toml index 26abab649b..ca7048bf63 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -13,37 +13,45 @@ default = ["simd"] [dependencies] arraygen = "0.1.13" -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" -slab = "0.4.2" spin_sleep = "1.0" sum_type = "0.2.0" tracing = { version = "0.1", default-features = false } vek = { version = "0.12.0", features = ["serde"] } +# Assets +directories-next = "2.0" +dot_vox = "4.0" +image = { version = "0.23.8", default-features = false, features = ["png"] } +notify = "5.0.0-pre.3" + +# Auth +authc = { git = "https://gitlab.com/veloren/auth.git", rev = "b943c85e4a38f5ec60cd18c34c73097640162bfe" } + +# Data structures +hashbrown = { version = "0.7.2", features = ["rayon", "serde", "nightly"] } +indexmap = "1.3.0" +slab = "0.4.2" + # 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" } +# Serde +ron = { version = "0.6", default-features = false } +serde = { version = "1.0.110", features = ["derive", "rc"] } +serde_json = "1.0.50" +serde_repr = "0.1.6" + # Tracy tracy-client = { version = "0.9.0", optional = true } diff --git a/common/src/clock.rs b/common/src/clock.rs index 3299a804b8..54a01762a6 100644 --- a/common/src/clock.rs +++ b/common/src/clock.rs @@ -28,9 +28,9 @@ pub struct Clock { total_tick_time: Duration, // Stats only // uses f32 so we have enough precision to display fps values while saving space - last_dts_millis: VecDeque>, - last_dts_millis_sorted: Vec>, - // Seconds + // This is in seconds + last_dts: VecDeque>, + last_dts_sorted: Vec>, last_busy_dts: VecDeque>, stats: ClockStats, } @@ -40,7 +40,7 @@ pub struct ClockStats { /// e.g. the total tick is 33ms, including 25ms sleeping. then this returns /// 8ms /// This is in seconds - pub average_busy_dt: f32, + pub average_busy_dt: Duration, /// avg over the last NUMBER_OF_OLD_DELTAS_KEPT ticks pub average_tps: f64, /// = 50% percentile @@ -62,8 +62,8 @@ impl Clock { last_sys_time: Instant::now(), last_dt: target_dt, total_tick_time: Duration::default(), - last_dts_millis: VecDeque::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), - last_dts_millis_sorted: Vec::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), + last_dts: VecDeque::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), + last_dts_sorted: Vec::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), last_busy_dts: VecDeque::with_capacity(NUMBER_OF_OLD_DELTAS_KEPT), stats: ClockStats::new(&[], &VecDeque::new()), } @@ -82,9 +82,9 @@ impl Clock { 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, &self.last_busy_dts); + self.last_dts_sorted = self.last_dts.iter().copied().collect(); + self.last_dts_sorted.sort_unstable(); + self.stats = ClockStats::new(&self.last_dts_sorted, &self.last_busy_dts); drop(guard); // Attempt to sleep to fill the gap. if let Some(sleep_dur) = self.target_dt.checked_sub(busy_delta) { @@ -93,14 +93,14 @@ impl Clock { let after_sleep_sys_time = Instant::now(); self.last_dt = after_sleep_sys_time.duration_since(self.last_sys_time); - if self.last_dts_millis.len() >= NUMBER_OF_OLD_DELTAS_KEPT { - self.last_dts_millis.pop_front(); + if self.last_dts.len() >= NUMBER_OF_OLD_DELTAS_KEPT { + self.last_dts.pop_front(); } if self.last_busy_dts.len() >= NUMBER_OF_OLD_DELTAS_KEPT { self.last_busy_dts.pop_front(); } - self.last_dts_millis.push_back( - NotNan::new(self.last_dt.as_secs_f32() * 1000.0) + self.last_dts.push_back( + NotNan::new(self.last_dt.as_secs_f32()) .expect("Duration::as_secs_f32 never returns NaN"), ); self.last_busy_dts.push_back( @@ -113,41 +113,40 @@ impl Clock { impl ClockStats { fn new(sorted: &[NotNan], busy_dt_list: &VecDeque>) -> 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().sum::>().into_inner() / len.max(1) as f32; + let average_frame_time = + sorted.iter().sum::>().into_inner() / sorted.len().max(1) as f32; let average_busy_dt = busy_dt_list.iter().sum::>().into_inner() / busy_dt_list.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 average_tps = 1.0 / average_frame_time as f64; + let (median_tps, percentile_90_tps, percentile_95_tps, percentile_99_tps) = + if sorted.len() >= NUMBER_OF_OLD_DELTAS_KEPT { + let median_frame_time = *sorted[sorted.len() / 2]; + let percentile_90_frame_time = + *sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.1) as usize]; + let percentile_95_frame_time = + *sorted[(NUMBER_OF_OLD_DELTAS_KEPT as f32 * 0.05) as usize]; + let percentile_99_frame_time = + *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); - let percentile_95_tps = NANOS_PER_SEC / (percentile_95_millis as f64 * NANOS_PER_MILLI); - let percentile_99_tps = NANOS_PER_SEC / (percentile_99_millis as f64 * NANOS_PER_MILLI); - ( - median_tps, - percentile_90_tps, - percentile_95_tps, - percentile_99_tps, - ) - } else { - let avg_tps = 1.0 / average_busy_dt as f64; - (avg_tps, avg_tps, avg_tps, avg_tps) - }; + let median_tps = 1.0 / median_frame_time as f64; + let percentile_90_tps = 1.0 / percentile_90_frame_time as f64; + let percentile_95_tps = 1.0 / percentile_95_frame_time as f64; + let percentile_99_tps = 1.0 / percentile_99_frame_time as f64; + ( + median_tps, + percentile_90_tps, + percentile_95_tps, + percentile_99_tps, + ) + } else { + let avg_tps = 1.0 / average_busy_dt as f64; + (avg_tps, avg_tps, avg_tps, avg_tps) + }; Self { - average_busy_dt, + average_busy_dt: Duration::from_secs_f32(average_busy_dt), average_tps, median_tps, percentile_90_tps, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index d1987291ee..de88275739 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -694,7 +694,7 @@ impl PlayState for SessionState { .toggle_debug .then(|| DebugInfo { tps: global_state.clock.stats().average_tps, - frame_time: Duration::from_secs_f32(global_state.clock.stats().average_busy_dt), + frame_time: global_state.clock.stats().average_busy_dt, ping_ms: self.client.borrow().get_ping_ms_rolling_avg(), coordinates: self .client