1use std::{
2 num::NonZeroUsize,
3 sync::{Arc, OnceLock},
4};
5
6use hashbrown::HashMap;
7
8use crate::timestamp::Timestamp;
9
10pub type SpanIndex = NonZeroUsize;
11
12pub struct Span {
13 pub parent: Option<SpanIndex>,
15 pub depth: u32,
16 pub start: Timestamp,
17 pub category: String,
18 pub name: String,
19 pub args: Vec<(String, String)>,
20
21 pub events: Vec<SpanEvent>,
23 pub is_complete: bool,
24
25 pub self_allocations: u64,
27 pub self_allocation_count: u64,
28 pub self_deallocations: u64,
29 pub self_deallocation_count: u64,
30
31 pub max_depth: OnceLock<u32>,
33 pub total_allocations: OnceLock<u64>,
34 pub total_deallocations: OnceLock<u64>,
35 pub total_persistent_allocations: OnceLock<u64>,
36 pub total_span_count: OnceLock<u64>,
37 pub total_allocation_count: OnceLock<u64>,
38
39 pub time_data: OnceLock<Box<SpanTimeData>>,
41 pub extra: OnceLock<Box<SpanExtra>>,
42 pub names: OnceLock<Box<SpanNames>>,
43}
44
45#[derive(Default)]
46pub struct SpanTimeData {
47 pub ignore_self_time: bool,
49
50 pub self_end: Timestamp,
52
53 pub self_time: Timestamp,
55
56 pub end: OnceLock<Timestamp>,
58 pub total_time: OnceLock<Timestamp>,
59 pub corrected_self_time: OnceLock<Timestamp>,
60 pub corrected_total_time: OnceLock<Timestamp>,
61}
62
63#[derive(Default)]
64pub struct SpanExtra {
65 pub graph: OnceLock<Vec<SpanGraphEvent>>,
66 pub bottom_up: OnceLock<Vec<Arc<SpanBottomUp>>>,
67 pub search_index: OnceLock<HashMap<String, Vec<SpanIndex>>>,
68}
69
70#[derive(Default)]
71pub struct SpanNames {
72 pub nice_name: OnceLock<(String, String)>,
74 pub group_name: OnceLock<String>,
75}
76
77impl Span {
78 pub fn time_data(&self) -> &SpanTimeData {
79 self.time_data.get_or_init(|| {
80 Box::new(SpanTimeData {
81 self_end: self.start,
82 ignore_self_time: &self.name == "thread",
83 ..Default::default()
84 })
85 })
86 }
87
88 pub fn time_data_mut(&mut self) -> &mut SpanTimeData {
89 self.time_data();
90 self.time_data.get_mut().unwrap()
91 }
92
93 pub fn extra(&self) -> &SpanExtra {
94 self.extra.get_or_init(Default::default)
95 }
96
97 pub fn names(&self) -> &SpanNames {
98 self.names.get_or_init(Default::default)
99 }
100}
101
102#[derive(Copy, Clone, PartialEq, Eq)]
103pub enum SpanEvent {
104 SelfTime { start: Timestamp, end: Timestamp },
105 Child { index: SpanIndex },
106}
107
108#[derive(Clone)]
109pub enum SpanGraphEvent {
110 #[allow(dead_code)]
112 SelfTime {
113 duration: Timestamp,
114 },
115 Child {
116 child: Arc<SpanGraph>,
117 },
118}
119
120pub struct SpanGraph {
121 pub root_spans: Vec<SpanIndex>,
123 pub recursive_spans: Vec<SpanIndex>,
124
125 pub max_depth: OnceLock<u32>,
127 pub events: OnceLock<Vec<SpanGraphEvent>>,
128 pub self_time: OnceLock<Timestamp>,
129 pub self_allocations: OnceLock<u64>,
130 pub self_deallocations: OnceLock<u64>,
131 pub self_persistent_allocations: OnceLock<u64>,
132 pub self_allocation_count: OnceLock<u64>,
133 pub total_time: OnceLock<Timestamp>,
134 pub total_allocations: OnceLock<u64>,
135 pub total_deallocations: OnceLock<u64>,
136 pub total_persistent_allocations: OnceLock<u64>,
137 pub total_allocation_count: OnceLock<u64>,
138 pub total_span_count: OnceLock<u64>,
139 pub corrected_self_time: OnceLock<Timestamp>,
140 pub corrected_total_time: OnceLock<Timestamp>,
141 pub bottom_up: OnceLock<Vec<Arc<SpanBottomUp>>>,
142}
143
144pub struct SpanBottomUp {
145 pub self_spans: Vec<SpanIndex>,
147 pub children: Vec<Arc<SpanBottomUp>>,
148 pub example_span: SpanIndex,
149
150 pub max_depth: OnceLock<u32>,
152 pub events: OnceLock<Vec<SpanGraphEvent>>,
153 pub self_time: OnceLock<Timestamp>,
154 pub corrected_self_time: OnceLock<Timestamp>,
155 pub self_allocations: OnceLock<u64>,
156 pub self_deallocations: OnceLock<u64>,
157 pub self_persistent_allocations: OnceLock<u64>,
158 pub self_allocation_count: OnceLock<u64>,
159}
160
161impl SpanBottomUp {
162 pub fn new(
163 self_spans: Vec<SpanIndex>,
164 example_span: SpanIndex,
165 children: Vec<Arc<SpanBottomUp>>,
166 ) -> Self {
167 Self {
168 self_spans,
169 children,
170 example_span,
171 max_depth: OnceLock::new(),
172 events: OnceLock::new(),
173 self_time: OnceLock::new(),
174 corrected_self_time: OnceLock::new(),
175 self_allocations: OnceLock::new(),
176 self_deallocations: OnceLock::new(),
177 self_persistent_allocations: OnceLock::new(),
178 self_allocation_count: OnceLock::new(),
179 }
180 }
181}