rprofiler/
block_stat.rs

1use std::{
2    time::Duration,
3    collections::BTreeMap,
4};
5
6pub struct BlockStatReport {
7    name: String,
8    avg_time: Duration,
9    global_percents: f32,
10    relative_parent_percents: f32,
11    children: Vec<BlockStatReport>,
12}
13
14impl BlockStatReport {
15    pub fn build_string(&mut self, report: &mut String) {
16        self.build_string_recurse(report, 0, 0)
17    }
18
19    fn build_string_recurse(&mut self, report: &mut String, depth: usize, max_name_len: usize) {
20        let name = self.name.replace("<", "&lt;").replace(">", "&gt;");
21
22        *report += &format!(
23            concat!(
24            "<tr>",
25            "<td style=\"padding-left: {}\">{}</td>",
26            "<td>{:6.2} %</td>",
27            "<td>{:6.2} %</td>",
28            "<td>{:9.4} ms</td>",
29            "</tr>\n"
30            ),
31            depth*25, name, self.global_percents, self.relative_parent_percents, self.avg_time.as_secs_f32()*1000.0
32        );
33
34        self.children.sort_by(|a, b| b.relative_parent_percents.partial_cmp(&a.relative_parent_percents).unwrap());
35
36        for child in self.children.iter_mut() {
37            child.build_string_recurse(report, depth + 1, max_name_len);
38        }
39    }
40}
41
42
43pub struct BlockStat {
44    pub(crate) name: &'static str,
45    pub(crate) total_time: Duration,
46    pub(crate) measure_count: u32,
47    pub(crate) children: BTreeMap<usize, Box<BlockStat>>,
48}
49
50impl BlockStat {
51    pub fn new(name: &'static str) -> BlockStat {
52        BlockStat {
53            name,
54            total_time: Duration::from_millis(0),
55            measure_count: 0,
56            children: BTreeMap::new(),
57        }
58    }
59
60    pub fn build_report(&self) -> BlockStatReport {
61        self.build_report_recurse(self.total_time, self.total_time, self.total_time, self.total_time)
62    }
63
64    fn build_report_recurse(&self, total_global_time: Duration, avg_global_time: Duration, total_parent_time: Duration, _avg_parent_time: Duration) -> BlockStatReport {
65        let avg_time = match self.measure_count > 0 {
66            true => self.total_time / self.measure_count,
67            false => self.total_time,
68        };
69
70        BlockStatReport {
71            name: {
72                let mut name = String::with_capacity(self.name.len());
73                let mut name_parts_iter = self.name.split("::");
74                while let Some(first_name_part) = name_parts_iter.next() {
75                    match name_parts_iter.clone().next() {
76                        Some(second_name_part) => {
77                            let first_name_part_simplified = first_name_part.to_lowercase().replace("_", "");
78                            let second_name_part_simplified = second_name_part.to_lowercase().replace("_", "");
79
80                            match first_name_part_simplified == second_name_part_simplified {
81                                true => {
82                                    name += "::";
83                                    name += second_name_part;
84                                    name_parts_iter.next();
85                                }
86                                false => {
87                                    name += "::";
88                                    name += first_name_part;
89                                }
90                            }
91                        }
92                        None => {
93                            name += "::";
94                            name += first_name_part;
95                        }
96                    }
97                }
98
99                name.strip_prefix("::").map(|a| a.to_owned()).unwrap_or(name)
100            },
101            avg_time,
102            global_percents: (self.total_time.as_secs_f32() / total_global_time.as_secs_f32())*100.0,
103            relative_parent_percents: (self.total_time.as_secs_f32() / total_parent_time.as_secs_f32())*100.0,
104            children: {
105                let total_parent_time: Duration = self.total_time;
106                let avg_parent_time: Duration = avg_time;
107                self.children.iter().map(|(_, stat)|
108                    stat.build_report_recurse(total_global_time, avg_global_time, total_parent_time, avg_parent_time)
109                ).collect()
110            },
111        }
112    }
113}