remove spancmp (#7409)
# Objective - This tool get less use than I hoped, as we gained more proficiency with other tracing tools like tracy ## Solution - Remove it
This commit is contained in:
		
							parent
							
								
									a61bf35c97
								
							
						
					
					
						commit
						daa45ebb4d
					
				
							
								
								
									
										1
									
								
								.github/workflows/post-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/post-release.yml
									
									
									
									
										vendored
									
									
								
							| @ -45,7 +45,6 @@ jobs: | |||||||
|             --exclude ci \ |             --exclude ci \ | ||||||
|             --exclude errors \ |             --exclude errors \ | ||||||
|             --exclude bevy-ios-example \ |             --exclude bevy-ios-example \ | ||||||
|             --exclude spancmp \ |  | ||||||
|             --exclude build-wasm-example |             --exclude build-wasm-example | ||||||
| 
 | 
 | ||||||
|       - name: Create PR |       - name: Create PR | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @ -42,7 +42,6 @@ jobs: | |||||||
|             --exclude ci \ |             --exclude ci \ | ||||||
|             --exclude errors \ |             --exclude errors \ | ||||||
|             --exclude bevy-ios-example \ |             --exclude bevy-ios-example \ | ||||||
|             --exclude spancmp \ |  | ||||||
|             --exclude build-wasm-example |             --exclude build-wasm-example | ||||||
| 
 | 
 | ||||||
|       - name: Create PR |       - name: Create PR | ||||||
|  | |||||||
| @ -19,7 +19,6 @@ members = [ | |||||||
|   "examples/android", |   "examples/android", | ||||||
|   "examples/ios", |   "examples/ios", | ||||||
|   "tools/ci", |   "tools/ci", | ||||||
|   "tools/spancmp", |  | ||||||
|   "tools/build-example-pages", |   "tools/build-example-pages", | ||||||
|   "tools/build-wasm-example", |   "tools/build-wasm-example", | ||||||
|   "errors", |   "errors", | ||||||
|  | |||||||
| @ -1,16 +0,0 @@ | |||||||
| [package] |  | ||||||
| name = "spancmp" |  | ||||||
| version = "0.1.0" |  | ||||||
| edition = "2021" |  | ||||||
| description = "compare spans for Bevy" |  | ||||||
| publish = false |  | ||||||
| license = "MIT OR Apache-2.0" |  | ||||||
| 
 |  | ||||||
| [dependencies] |  | ||||||
| serde_json = "1.0" |  | ||||||
| serde = { version = "1.0", features = ["derive"] } |  | ||||||
| clap = { version = "4.0", features = ["derive"] } |  | ||||||
| regex = "1.5" |  | ||||||
| termcolor = "1.1" |  | ||||||
| bevy_utils = { path = "../../crates/bevy_utils", version = "0.9.0" } |  | ||||||
| lazy_static = "1.4" |  | ||||||
| @ -1,162 +0,0 @@ | |||||||
| //! helper to extract span stats from a chrome trace file
 |  | ||||||
| //! spec: <https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.puwqg050lyuy>
 |  | ||||||
| 
 |  | ||||||
| use std::ops::Div; |  | ||||||
| 
 |  | ||||||
| use clap::Parser; |  | ||||||
| use parse::read_trace; |  | ||||||
| use regex::Regex; |  | ||||||
| use termcolor::{ColorChoice, StandardStream}; |  | ||||||
| 
 |  | ||||||
| use crate::pretty::{print_spanstats, set_bold, simplify_name}; |  | ||||||
| 
 |  | ||||||
| mod parse; |  | ||||||
| mod pretty; |  | ||||||
| 
 |  | ||||||
| #[derive(Parser, Debug)] |  | ||||||
| struct Args { |  | ||||||
|     #[arg(short, long, default_value_t = 0.0)] |  | ||||||
|     /// Filter spans that have an average shorter than the threshold
 |  | ||||||
|     threshold: f32, |  | ||||||
| 
 |  | ||||||
|     #[arg(short, long)] |  | ||||||
|     /// Filter spans by name matching the pattern
 |  | ||||||
|     pattern: Option<Regex>, |  | ||||||
| 
 |  | ||||||
|     #[arg(short, long)] |  | ||||||
|     /// Simplify system names
 |  | ||||||
|     short: bool, |  | ||||||
| 
 |  | ||||||
|     trace: String, |  | ||||||
|     /// Optional, second trace to compare
 |  | ||||||
|     second_trace: Option<String>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn main() { |  | ||||||
|     let cli = Args::parse(); |  | ||||||
| 
 |  | ||||||
|     // Setup stdout to support colors
 |  | ||||||
|     let mut stdout = StandardStream::stdout(ColorChoice::Auto); |  | ||||||
| 
 |  | ||||||
|     // Read the first trace file
 |  | ||||||
|     let reference = read_trace(cli.trace); |  | ||||||
|     if let Some(comparison) = cli.second_trace { |  | ||||||
|         // Read the second trace file
 |  | ||||||
|         let mut comparison = read_trace(comparison); |  | ||||||
| 
 |  | ||||||
|         reference |  | ||||||
|             .iter() |  | ||||||
|             .filter(|(_, stats)| filter_by_threshold(stats, cli.threshold)) |  | ||||||
|             .filter(|(name, _)| filter_by_pattern(name, cli.pattern.as_ref())) |  | ||||||
|             .for_each(|(span, reference)| { |  | ||||||
|                 // for each span in the first trace
 |  | ||||||
|                 set_bold(&mut stdout, true); |  | ||||||
|                 if cli.short { |  | ||||||
|                     println!("{}", simplify_name(span)); |  | ||||||
|                 } else { |  | ||||||
|                     println!("{span}"); |  | ||||||
|                 } |  | ||||||
|                 set_bold(&mut stdout, false); |  | ||||||
|                 print!("  "); |  | ||||||
|                 let comparison = comparison.remove(span); |  | ||||||
|                 print_spanstats(&mut stdout, Some(reference), comparison.as_ref(), false); |  | ||||||
|             }); |  | ||||||
|         comparison |  | ||||||
|             .iter() |  | ||||||
|             .filter(|(_, stats)| filter_by_threshold(stats, cli.threshold)) |  | ||||||
|             .filter(|(name, _)| filter_by_pattern(name, cli.pattern.as_ref())) |  | ||||||
|             .for_each(|(span, comparison)| { |  | ||||||
|                 // print the spans only present in the second trace
 |  | ||||||
|                 set_bold(&mut stdout, true); |  | ||||||
|                 if cli.short { |  | ||||||
|                     println!("{}", simplify_name(span)); |  | ||||||
|                 } else { |  | ||||||
|                     println!("{span}"); |  | ||||||
|                 } |  | ||||||
|                 set_bold(&mut stdout, false); |  | ||||||
|                 print!("  "); |  | ||||||
|                 print_spanstats(&mut stdout, None, Some(comparison), false); |  | ||||||
|             }); |  | ||||||
|     } else { |  | ||||||
|         // just print stats from the first trace
 |  | ||||||
|         reference |  | ||||||
|             .iter() |  | ||||||
|             .filter(|(_, stats)| filter_by_threshold(stats, cli.threshold)) |  | ||||||
|             .filter(|(name, _)| filter_by_pattern(name, cli.pattern.as_ref())) |  | ||||||
|             .for_each(|(span, reference)| { |  | ||||||
|                 set_bold(&mut stdout, true); |  | ||||||
|                 if cli.short { |  | ||||||
|                     println!("{}", simplify_name(span)); |  | ||||||
|                 } else { |  | ||||||
|                     println!("{span}"); |  | ||||||
|                 } |  | ||||||
|                 set_bold(&mut stdout, false); |  | ||||||
|                 print!("  "); |  | ||||||
|                 print_spanstats(&mut stdout, Some(reference), None, true); |  | ||||||
|             }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn filter_by_threshold(span_stats: &SpanStats, threshold: f32) -> bool { |  | ||||||
|     span_stats.avg > threshold |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn filter_by_pattern(name: &str, pattern: Option<&Regex>) -> bool { |  | ||||||
|     if let Some(pattern) = pattern { |  | ||||||
|         pattern.is_match(name) |  | ||||||
|     } else { |  | ||||||
|         true |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct SpanStats { |  | ||||||
|     pub count: usize, |  | ||||||
|     pub avg: f32, |  | ||||||
|     pub min: f32, |  | ||||||
|     pub max: f32, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Default for SpanStats { |  | ||||||
|     fn default() -> Self { |  | ||||||
|         Self { |  | ||||||
|             count: 0, |  | ||||||
|             avg: 0.0, |  | ||||||
|             min: f32::MAX, |  | ||||||
|             max: 0.0, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl SpanStats { |  | ||||||
|     fn add_span(&mut self, duration: f32) { |  | ||||||
|         if duration < self.min { |  | ||||||
|             self.min = duration; |  | ||||||
|         } |  | ||||||
|         if duration > self.max { |  | ||||||
|             self.max = duration; |  | ||||||
|         } |  | ||||||
|         self.avg = (self.avg * self.count as f32 + duration) / (self.count as f32 + 1.0); |  | ||||||
|         self.count += 1; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct SpanRelative { |  | ||||||
|     count: f32, |  | ||||||
|     avg: f32, |  | ||||||
|     min: f32, |  | ||||||
|     max: f32, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Div for &SpanStats { |  | ||||||
|     type Output = SpanRelative; |  | ||||||
| 
 |  | ||||||
|     fn div(self, rhs: Self) -> Self::Output { |  | ||||||
|         Self::Output { |  | ||||||
|             count: self.count as f32 / rhs.count as f32, |  | ||||||
|             avg: self.avg / rhs.avg, |  | ||||||
|             min: self.min / rhs.min, |  | ||||||
|             max: self.max / rhs.max, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,96 +0,0 @@ | |||||||
| use std::{ |  | ||||||
|     cell::RefCell, |  | ||||||
|     collections::HashMap, |  | ||||||
|     fs::File, |  | ||||||
|     io::{BufReader, Read}, |  | ||||||
|     rc::Rc, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| use serde::Deserialize; |  | ||||||
| use serde_json::Deserializer; |  | ||||||
| 
 |  | ||||||
| use crate::SpanStats; |  | ||||||
| 
 |  | ||||||
| /// A span from the trace
 |  | ||||||
| #[derive(Deserialize, Debug)] |  | ||||||
| struct Span { |  | ||||||
|     /// name
 |  | ||||||
|     name: String, |  | ||||||
|     /// phase
 |  | ||||||
|     ph: String, |  | ||||||
|     /// timestamp
 |  | ||||||
|     ts: f32, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// Ignore entries in the trace that are not a span
 |  | ||||||
| #[derive(Deserialize, Debug)] |  | ||||||
| struct Ignore {} |  | ||||||
| 
 |  | ||||||
| /// deserialize helper
 |  | ||||||
| #[derive(Deserialize, Debug)] |  | ||||||
| #[serde(untagged)] |  | ||||||
| enum SpanOrIgnore { |  | ||||||
|     /// deserialize as a span
 |  | ||||||
|     Span(Span), |  | ||||||
|     /// catchall that didn't match a span
 |  | ||||||
|     Ignore(Ignore), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Clone)] |  | ||||||
| struct SkipperWrapper { |  | ||||||
|     reader: Rc<RefCell<BufReader<File>>>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl SkipperWrapper { |  | ||||||
|     fn from(mut reader: BufReader<File>) -> SkipperWrapper { |  | ||||||
|         let _ = reader.seek_relative(1); |  | ||||||
| 
 |  | ||||||
|         Self { |  | ||||||
|             reader: Rc::new(RefCell::new(reader)), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn skip(&self) { |  | ||||||
|         let _ = self.reader.borrow_mut().seek_relative(1); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Read for SkipperWrapper { |  | ||||||
|     fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> { |  | ||||||
|         self.reader.borrow_mut().read(buf) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn read_trace(file: String) -> HashMap<String, SpanStats> { |  | ||||||
|     let file = File::open(file).unwrap(); |  | ||||||
|     let reader = BufReader::new(file); |  | ||||||
|     let reader_wrapper = SkipperWrapper::from(reader); |  | ||||||
| 
 |  | ||||||
|     let spans = Deserializer::from_reader(reader_wrapper.clone()).into_iter::<SpanOrIgnore>(); |  | ||||||
| 
 |  | ||||||
|     let mut open_spans: HashMap<String, f32> = HashMap::new(); |  | ||||||
|     let mut all_spans_stats: HashMap<String, SpanStats> = HashMap::new(); |  | ||||||
|     spans |  | ||||||
|         .flat_map(move |s| { |  | ||||||
|             reader_wrapper.skip(); |  | ||||||
| 
 |  | ||||||
|             if let Ok(SpanOrIgnore::Span(span)) = s { |  | ||||||
|                 Some(span) |  | ||||||
|             } else { |  | ||||||
|                 None |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|         .for_each(|s| { |  | ||||||
|             if s.ph == "B" { |  | ||||||
|                 open_spans.insert(s.name.clone(), s.ts); |  | ||||||
|             } else if s.ph == "E" { |  | ||||||
|                 let begin = open_spans.remove(&s.name).unwrap(); |  | ||||||
|                 all_spans_stats |  | ||||||
|                     .entry(s.name) |  | ||||||
|                     .or_default() |  | ||||||
|                     .add_span(s.ts - begin); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|     all_spans_stats |  | ||||||
| } |  | ||||||
| @ -1,234 +0,0 @@ | |||||||
| use bevy_utils::get_short_name; |  | ||||||
| use lazy_static::lazy_static; |  | ||||||
| use regex::Regex; |  | ||||||
| use termcolor::{Color, ColorSpec, StandardStream, WriteColor}; |  | ||||||
| 
 |  | ||||||
| use crate::SpanStats; |  | ||||||
| 
 |  | ||||||
| pub fn print_spanstats( |  | ||||||
|     stdout: &mut StandardStream, |  | ||||||
|     reference: Option<&SpanStats>, |  | ||||||
|     comparison: Option<&SpanStats>, |  | ||||||
|     reference_only: bool, |  | ||||||
| ) { |  | ||||||
|     match (reference, comparison) { |  | ||||||
|         (Some(reference), Some(comparison)) if !reference_only => { |  | ||||||
|             let relative = comparison / reference; |  | ||||||
| 
 |  | ||||||
|             print!("[count: {:8} | {:8} | ", reference.count, comparison.count); |  | ||||||
|             print_relative(stdout, relative.count); |  | ||||||
|             print!("]  [min: "); |  | ||||||
|             print_delta_time_us(reference.min); |  | ||||||
|             print!(" | "); |  | ||||||
|             print_delta_time_us(comparison.min); |  | ||||||
|             print!(" | "); |  | ||||||
|             print_relative(stdout, relative.min); |  | ||||||
|             print!("]  [avg: "); |  | ||||||
|             print_delta_time_us(reference.avg); |  | ||||||
|             print!(" | "); |  | ||||||
|             print_delta_time_us(comparison.avg); |  | ||||||
|             print!(" | "); |  | ||||||
|             print_relative(stdout, relative.avg); |  | ||||||
|             print!("]  [max: "); |  | ||||||
|             print_delta_time_us(reference.max); |  | ||||||
|             print!(" | "); |  | ||||||
|             print_delta_time_us(comparison.max); |  | ||||||
|             print!(" | "); |  | ||||||
|             print_relative(stdout, relative.max); |  | ||||||
|             println!("]"); |  | ||||||
|         } |  | ||||||
|         (Some(reference), None) if !reference_only => { |  | ||||||
|             print!( |  | ||||||
|                 "[count: {:8} |          |        ]  [min:  ", |  | ||||||
|                 reference.count |  | ||||||
|             ); |  | ||||||
|             print_delta_time_us(reference.min); |  | ||||||
|             print!(" |         |         ]  [avg: "); |  | ||||||
|             print_delta_time_us(reference.avg); |  | ||||||
|             print!(" |         |         ]  [max: "); |  | ||||||
|             print_delta_time_us(reference.max); |  | ||||||
|             println!(" |         |         ]"); |  | ||||||
|         } |  | ||||||
|         (None, Some(comparison)) => { |  | ||||||
|             print!("[count:          | {:8} |         ", comparison.count); |  | ||||||
|             print!("]  [min:         | "); |  | ||||||
|             print_delta_time_us(comparison.min); |  | ||||||
|             print!(" |         ]  [avg:         | "); |  | ||||||
|             print_delta_time_us(comparison.avg); |  | ||||||
|             print!(" |         ]  [max:         | "); |  | ||||||
|             print_delta_time_us(comparison.max); |  | ||||||
|             println!(" |         ]"); |  | ||||||
|         } |  | ||||||
|         (Some(reference), _) if reference_only => { |  | ||||||
|             print!("[count: {:8}]  [min: ", reference.count); |  | ||||||
|             print_delta_time_us(reference.min); |  | ||||||
|             print!("]  [avg: "); |  | ||||||
|             print_delta_time_us(reference.avg); |  | ||||||
|             print!("]  [max: "); |  | ||||||
|             print_delta_time_us(reference.max); |  | ||||||
|             println!("]"); |  | ||||||
|         } |  | ||||||
|         _ => {} |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const MARGIN_PERCENT: f32 = 2.0; |  | ||||||
| fn print_relative(stdout: &mut StandardStream, v: f32) { |  | ||||||
|     let v_delta_percent = if v.is_nan() { 0.0 } else { (v - 1.0) * 100.0 }; |  | ||||||
|     set_fg( |  | ||||||
|         stdout, |  | ||||||
|         if v_delta_percent > MARGIN_PERCENT { |  | ||||||
|             Color::Red |  | ||||||
|         } else if v_delta_percent < -MARGIN_PERCENT { |  | ||||||
|             Color::Green |  | ||||||
|         } else { |  | ||||||
|             Color::White |  | ||||||
|         }, |  | ||||||
|     ); |  | ||||||
|     if v_delta_percent > MARGIN_PERCENT { |  | ||||||
|         print!("+"); |  | ||||||
|     } else if v_delta_percent >= -MARGIN_PERCENT { |  | ||||||
|         print!(" "); |  | ||||||
|     } else { |  | ||||||
|         print!("-"); |  | ||||||
|     } |  | ||||||
|     print_base10f32_fixed_width(v_delta_percent.abs(), 1.0); |  | ||||||
|     print!("%"); |  | ||||||
|     set_fg(stdout, Color::White); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Try to print time values using 4 numeric digits, a decimal point, and the unit
 |  | ||||||
| const ONE_US_IN_SECONDS: f32 = 1e-6; |  | ||||||
| 
 |  | ||||||
| fn print_delta_time_us(dt_us: f32) { |  | ||||||
|     print_base10f32_fixed_width(dt_us, ONE_US_IN_SECONDS); |  | ||||||
|     print!("s"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn print_base10f32_fixed_width(v: f32, v_scale: f32) { |  | ||||||
|     Scale::from_value_and_scale(v, v_scale).print_with_scale(v, v_scale); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct Scale { |  | ||||||
|     name: &'static str, |  | ||||||
|     scale_factor: f32, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Scale { |  | ||||||
|     pub const TERA: f32 = 1e12; |  | ||||||
|     pub const GIGA: f32 = 1e9; |  | ||||||
|     pub const MEGA: f32 = 1e6; |  | ||||||
|     pub const KILO: f32 = 1e3; |  | ||||||
|     pub const UNIT: f32 = 1e0; |  | ||||||
|     pub const MILLI: f32 = 1e-3; |  | ||||||
|     pub const MICRO: f32 = 1e-6; |  | ||||||
|     pub const NANO: f32 = 1e-9; |  | ||||||
|     pub const PICO: f32 = 1e-12; |  | ||||||
| 
 |  | ||||||
|     pub fn from_value_and_scale(v: f32, v_scale: f32) -> Self { |  | ||||||
|         assert!(v >= 0.0); |  | ||||||
|         if v == 0.0 { |  | ||||||
|             Self { |  | ||||||
|                 name: " ", |  | ||||||
|                 scale_factor: Self::UNIT, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::TERA { |  | ||||||
|             Self { |  | ||||||
|                 name: "T", |  | ||||||
|                 scale_factor: Self::TERA, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::GIGA { |  | ||||||
|             Self { |  | ||||||
|                 name: "G", |  | ||||||
|                 scale_factor: Self::GIGA, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::MEGA { |  | ||||||
|             Self { |  | ||||||
|                 name: "M", |  | ||||||
|                 scale_factor: Self::MEGA, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::KILO { |  | ||||||
|             Self { |  | ||||||
|                 name: "k", |  | ||||||
|                 scale_factor: Self::KILO, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::UNIT { |  | ||||||
|             Self { |  | ||||||
|                 name: " ", |  | ||||||
|                 scale_factor: Self::UNIT, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::MILLI { |  | ||||||
|             Self { |  | ||||||
|                 name: "m", |  | ||||||
|                 scale_factor: Self::MILLI, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::MICRO { |  | ||||||
|             Self { |  | ||||||
|                 name: "µ", |  | ||||||
|                 scale_factor: Self::MICRO, |  | ||||||
|             } |  | ||||||
|         } else if v * v_scale >= Self::NANO { |  | ||||||
|             Self { |  | ||||||
|                 name: "n", |  | ||||||
|                 scale_factor: Self::NANO, |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             Self { |  | ||||||
|                 name: "p", |  | ||||||
|                 scale_factor: Self::PICO, |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn print(&self, v: f32) { |  | ||||||
|         // NOTE: Hacks for rounding to decimal places to ensure precision is correct
 |  | ||||||
|         let precision = if ((v * 10.0).round() / 10.0) >= 100.0 { |  | ||||||
|             1 |  | ||||||
|         } else if ((v * 100.0).round() / 100.0) >= 10.0 { |  | ||||||
|             2 |  | ||||||
|         } else { |  | ||||||
|             3 |  | ||||||
|         }; |  | ||||||
|         print!("{v:5.precision$}{}", self.name); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn print_with_scale(&self, v: f32, v_scale: f32) { |  | ||||||
|         self.print(v * v_scale / self.scale_factor); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| lazy_static! { |  | ||||||
|     static ref SYSTEM_NAME: Regex = Regex::new(r#"system: name="([^"]+)""#).unwrap(); |  | ||||||
|     static ref SYSTEM_OVERHEAD: Regex = Regex::new(r#"system overhead: name="([^"]+)""#).unwrap(); |  | ||||||
|     static ref SYSTEM_COMMANDS: Regex = Regex::new(r#"system_commands: name="([^"]+)""#).unwrap(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn simplify_name(name: &str) -> String { |  | ||||||
|     if let Some(captures) = SYSTEM_NAME.captures(name) { |  | ||||||
|         return format!(r#"system: name="{}""#, get_short_name(&captures[1])); |  | ||||||
|     } |  | ||||||
|     if let Some(captures) = SYSTEM_OVERHEAD.captures(name) { |  | ||||||
|         return format!( |  | ||||||
|             r#"system overhead: name="{}""#, |  | ||||||
|             get_short_name(&captures[1]) |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
|     if let Some(captures) = SYSTEM_COMMANDS.captures(name) { |  | ||||||
|         return format!( |  | ||||||
|             r#"system_commands: name="{}""#, |  | ||||||
|             get_short_name(&captures[1]) |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
|     name.to_string() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn set_fg(stdout: &mut StandardStream, color: Color) { |  | ||||||
|     stdout |  | ||||||
|         .set_color(ColorSpec::new().set_fg(Some(color))) |  | ||||||
|         .unwrap(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn set_bold(stdout: &mut StandardStream, bold: bool) { |  | ||||||
|     stdout.set_color(ColorSpec::new().set_bold(bold)).unwrap(); |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 François
						François