profiler.rs (2932B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use std::collections::VecDeque; 6 7 #[derive(Debug)] 8 pub struct GraphStats { 9 pub min: f64, 10 pub avg: f64, 11 pub max: f64, 12 pub sum: f64, 13 pub samples: usize, 14 } 15 16 pub struct Graph { 17 pub name: String, 18 pub values: VecDeque<f64>, 19 } 20 21 impl Graph { 22 pub fn new(name: &str, max_samples: usize) -> Self { 23 let mut values = VecDeque::new(); 24 values.reserve(max_samples); 25 26 Graph { 27 name: name.into(), 28 values 29 } 30 } 31 32 pub fn push(&mut self, val: f64) { 33 if self.values.len() == self.values.capacity() { 34 self.values.pop_back(); 35 } 36 self.values.push_front(val); 37 } 38 39 pub fn stats(&self) -> GraphStats { 40 let mut stats = GraphStats { 41 min: f64::MAX, 42 avg: 0.0, 43 max: -f64::MAX, 44 sum: 0.0, 45 samples: 0, 46 }; 47 48 let mut samples = 0; 49 for value in &self.values { 50 if value.is_finite() { 51 stats.min = stats.min.min(*value); 52 stats.max = stats.max.max(*value); 53 stats.sum += *value; 54 samples += 1; 55 } 56 } 57 58 if samples > 0 { 59 stats.avg = stats.sum / samples as f64; 60 stats.samples = samples; 61 } else { 62 stats.min = 0.0; 63 stats.max = 0.0; 64 } 65 66 stats 67 } 68 } 69 70 pub fn ui(app: &mut super::Gui, ui: &mut egui::Ui) { 71 for graph in app.data_model.profile_graphs.values() { 72 let stats = graph.stats(); 73 74 ui.label(&graph.name); 75 76 let (response, painter) = ui.allocate_painter( 77 egui::vec2(1024.0, 128.0), 78 egui::Sense::hover(), 79 ); 80 81 let rect = response.rect; 82 83 // Background 84 painter.rect_filled(rect, 0.0, egui::Color32::from_rgb(77, 77, 77)); 85 86 let max_samples = graph.values.capacity() as f32; 87 let w = rect.width() / max_samples; 88 let h = rect.height(); 89 90 let color_t0 = egui::Color32::from_rgb(0, 255, 0); 91 92 for (index, sample) in graph.values.iter().enumerate() { 93 if !sample.is_finite() { 94 continue; 95 } 96 let sample = *sample as f32; 97 let x1 = rect.right() - index as f32 * w; 98 let x0 = x1 - w; 99 100 let y0 = rect.bottom() - (sample / stats.max as f32) * h; 101 let y1 = rect.bottom(); 102 103 let rect = egui::Rect::from_min_max( 104 egui::pos2(x0, y0), 105 egui::pos2(x1, y1), 106 ); 107 108 painter.rect_filled(rect, 0.0, color_t0); 109 } 110 111 ui.label(format!("Min: {:.2}, Avg: {:.2}, Max: {:.2}", stats.min, stats.avg, stats.max)); 112 } 113 }