From 5d4adb77433933807f5b3876c88fc044a5808e4f Mon Sep 17 00:00:00 2001 From: Ryan Walters Date: Thu, 28 Aug 2025 14:12:23 -0500 Subject: [PATCH] refactor: merge 'formatting' submodule into 'profiling' --- src/systems/formatting.rs | 107 -------------------------------------- src/systems/mod.rs | 1 - src/systems/profiling.rs | 106 +++++++++++++++++++++++++++++++++++-- tests/formatting.rs | 2 +- 4 files changed, 104 insertions(+), 112 deletions(-) delete mode 100644 src/systems/formatting.rs diff --git a/src/systems/formatting.rs b/src/systems/formatting.rs deleted file mode 100644 index 1b4e93e..0000000 --- a/src/systems/formatting.rs +++ /dev/null @@ -1,107 +0,0 @@ -use num_width::NumberWidth; -use smallvec::SmallVec; -use std::time::Duration; -use strum::EnumCount; - -use crate::systems::profiling::SystemId; - -// Helper to split a duration into a integer, decimal, and unit -fn get_value(duration: &Duration) -> (u64, u32, &'static str) { - let (int, decimal, unit) = match duration { - // if greater than 1 second, return as seconds - n if n >= &Duration::from_secs(1) => { - let secs = n.as_secs(); - let decimal = n.as_millis() as u64 % 1000; - (secs, decimal as u32, "s") - } - // if greater than 1 millisecond, return as milliseconds - n if n >= &Duration::from_millis(1) => { - let ms = n.as_millis() as u64; - let decimal = n.as_micros() as u64 % 1000; - (ms, decimal as u32, "ms") - } - // if greater than 1 microsecond, return as microseconds - n if n >= &Duration::from_micros(1) => { - let us = n.as_micros() as u64; - let decimal = n.as_nanos() as u64 % 1000; - (us, decimal as u32, "µs") - } - // otherwise, return as nanoseconds - n => { - let ns = n.as_nanos() as u64; - (ns, 0, "ns") - } - }; - - (int, decimal, unit) -} - -/// Formats timing data into a vector of strings with proper alignment -pub fn format_timing_display( - timing_data: impl IntoIterator, -) -> SmallVec<[String; SystemId::COUNT]> { - let mut iter = timing_data.into_iter().peekable(); - if iter.peek().is_none() { - return SmallVec::new(); - } - - struct Entry { - name: String, - avg_int: u64, - avg_decimal: u32, - avg_unit: &'static str, - std_int: u64, - std_decimal: u32, - std_unit: &'static str, - } - - let entries = iter - .map(|(name, avg, std_dev)| { - let (avg_int, avg_decimal, avg_unit) = get_value(&avg); - let (std_int, std_decimal, std_unit) = get_value(&std_dev); - - Entry { - name: name.clone(), - avg_int, - avg_decimal, - avg_unit, - std_int, - std_decimal, - std_unit, - } - }) - .collect::>(); - - 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), - ) - }); - - entries.iter().map(|e| { - format!( - "{name:max_name_width$} : {avg_int:max_avg_int_width$}.{avg_decimal:>() -} diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 6ac39da..55bffc4 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -8,7 +8,6 @@ pub mod blinking; pub mod collision; pub mod components; pub mod debug; -pub mod formatting; pub mod ghost; pub mod input; pub mod item; diff --git a/src/systems/profiling.rs b/src/systems/profiling.rs index 40e912b..e2526f6 100644 --- a/src/systems/profiling.rs +++ b/src/systems/profiling.rs @@ -2,6 +2,7 @@ use bevy_ecs::system::IntoSystem; use bevy_ecs::{resource::Resource, system::System}; use circular_buffer::CircularBuffer; use micromap::Map; +use num_width::NumberWidth; use parking_lot::{Mutex, RwLock}; use smallvec::SmallVec; use std::fmt::Display; @@ -10,8 +11,6 @@ use strum::EnumCount; use strum_macros::{EnumCount, IntoStaticStr}; use thousands::Separable; -use crate::systems::formatting; - /// The maximum number of systems that can be profiled. Must not be exceeded, or it will panic. const MAX_SYSTEMS: usize = SystemId::COUNT; /// The number of durations to keep in the circular buffer. @@ -159,7 +158,7 @@ impl SystemTimings { } // Use the formatting module to format the data - formatting::format_timing_display(timing_data) + format_timing_display(timing_data) } } @@ -184,3 +183,104 @@ where } } } + +// Helper to split a duration into a integer, decimal, and unit +fn get_value(duration: &Duration) -> (u64, u32, &'static str) { + let (int, decimal, unit) = match duration { + // if greater than 1 second, return as seconds + n if n >= &Duration::from_secs(1) => { + let secs = n.as_secs(); + let decimal = n.as_millis() as u64 % 1000; + (secs, decimal as u32, "s") + } + // if greater than 1 millisecond, return as milliseconds + n if n >= &Duration::from_millis(1) => { + let ms = n.as_millis() as u64; + let decimal = n.as_micros() as u64 % 1000; + (ms, decimal as u32, "ms") + } + // if greater than 1 microsecond, return as microseconds + n if n >= &Duration::from_micros(1) => { + let us = n.as_micros() as u64; + let decimal = n.as_nanos() as u64 % 1000; + (us, decimal as u32, "µs") + } + // otherwise, return as nanoseconds + n => { + let ns = n.as_nanos() as u64; + (ns, 0, "ns") + } + }; + + (int, decimal, unit) +} + +/// Formats timing data into a vector of strings with proper alignment +pub fn format_timing_display( + timing_data: impl IntoIterator, +) -> SmallVec<[String; SystemId::COUNT]> { + let mut iter = timing_data.into_iter().peekable(); + if iter.peek().is_none() { + return SmallVec::new(); + } + + struct Entry { + name: String, + avg_int: u64, + avg_decimal: u32, + avg_unit: &'static str, + std_int: u64, + std_decimal: u32, + std_unit: &'static str, + } + + let entries = iter + .map(|(name, avg, std_dev)| { + let (avg_int, avg_decimal, avg_unit) = get_value(&avg); + let (std_int, std_decimal, std_unit) = get_value(&std_dev); + + Entry { + name: name.clone(), + avg_int, + avg_decimal, + avg_unit, + std_int, + std_decimal, + std_unit, + } + }) + .collect::>(); + + 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), + ) + }); + + entries.iter().map(|e| { + format!( + "{name:max_name_width$} : {avg_int:max_avg_int_width$}.{avg_decimal:>() +} diff --git a/tests/formatting.rs b/tests/formatting.rs index 91e6a22..35561de 100644 --- a/tests/formatting.rs +++ b/tests/formatting.rs @@ -1,4 +1,4 @@ -use pacman::systems::formatting::format_timing_display; +use pacman::systems::profiling::format_timing_display; use std::time::Duration; use pretty_assertions::assert_eq;