bp3d_debug/profiler/
section.rs1use super::instant::get_time;
30use crate::field::FieldSet;
31use crate::util::Location;
32use std::num::NonZeroU32;
33use std::sync::OnceLock;
34
35#[repr(u8)]
36#[derive(Debug, Copy, Clone, Eq, PartialEq)]
37pub enum Level {
38 Critical = 0,
40
41 Periodic = 1,
43
44 Event = 2,
46}
47
48pub struct Entered<'a, const N: usize> {
49 id: NonZeroU32,
50 start: u64,
51 fields: FieldSet<'a, N>,
52}
53
54impl<const N: usize> Drop for Entered<'_, N> {
55 fn drop(&mut self) {
56 let end = get_time();
57 crate::engine::get().section_record(self.id, self.start, end, self.fields.as_ref());
58 }
59}
60
61pub struct Section {
62 name: &'static str,
63 location: Location,
64 level: Level,
65 parent: Option<&'static Section>,
66 id: OnceLock<NonZeroU32>,
67}
68
69impl Section {
70 pub const fn new(name: &'static str, location: Location, level: Level) -> Self {
71 Self {
72 name,
73 location,
74 level,
75 parent: None,
76 id: OnceLock::new(),
77 }
78 }
79
80 pub const fn set_parent(mut self, parent: &'static Section) -> Self {
81 self.parent = Some(parent);
82 self
83 }
84
85 pub fn name(&self) -> &'static str {
86 self.name
87 }
88
89 pub fn location(&self) -> &Location {
90 &self.location
91 }
92
93 pub fn level(&self) -> Level {
94 self.level
95 }
96
97 pub fn parent(&self) -> Option<&'static Section> {
98 self.parent
99 }
100
101 pub fn get_id(&'static self) -> &'static NonZeroU32 {
102 self.id
103 .get_or_init(|| crate::engine::get().section_register(self))
104 }
105
106 pub fn enter<'a, const N: usize>(&'static self, fields: FieldSet<'a, N>) -> Entered<'a, N> {
107 let id = self.get_id();
108 Entered {
109 id: *id,
110 start: get_time(),
111 fields,
112 }
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use crate::field::FieldSet;
119 use crate::profiler::section::{Level, Section};
120 use crate::{fields, location, profiler_section_start};
121
122 #[test]
123 fn basic() {
124 static _SECTION: Section = Section::new("api_test", location!(), Level::Event);
125 }
126
127 #[test]
128 fn api_test() {
129 static SECTION: Section = Section::new("api_test", location!(), Level::Event);
130 static _SECTION2: Section =
131 Section::new("api_test2", location!(), Level::Event).set_parent(&SECTION);
132 SECTION.enter(FieldSet::new(fields!()));
133 SECTION.enter(FieldSet::new(fields!({ test = 42 })));
134 SECTION.enter(FieldSet::new(fields!({ test = "test 123" })));
135 SECTION.enter(FieldSet::new(fields!({ test = 42.42 })));
136 SECTION.enter(FieldSet::new(fields!({test=?Level::Event})));
137 SECTION.enter(FieldSet::new(fields!({test=?Level::Event} {test2=42})));
138 let value = 32;
139 let str = "this is a test";
140 let lvl = Level::Event;
141 SECTION.enter(FieldSet::new(fields!({value} {str} {?lvl} {test = value})));
142 }
143
144 #[test]
145 fn api_test2() {
146 let value = 32;
147 let str = "this is a test";
148 let lvl = Level::Event;
149 profiler_section_start!(API_TEST, Level::Event);
150 profiler_section_start!(API2_TEST: API_TEST, Level::Event);
151 profiler_section_start!(API3_TEST_WITH_PARAMS: API2_TEST, Level::Event, {value} {str} {?lvl} {test=value});
152 }
153}