turbo_trace_server/
span_bottom_up_ref.rs1use std::{
2 collections::VecDeque,
3 fmt::{Debug, Formatter},
4 sync::Arc,
5};
6
7use crate::{
8 FxIndexMap,
9 span::{SpanBottomUp, SpanGraphEvent, SpanIndex},
10 span_graph_ref::{SpanGraphEventRef, SpanGraphRef, event_map_to_list},
11 span_ref::SpanRef,
12 store::{SpanId, Store},
13 timestamp::Timestamp,
14};
15
16pub struct SpanBottomUpRef<'a> {
17 pub(crate) bottom_up: Arc<SpanBottomUp>,
18 pub(crate) store: &'a Store,
19}
20
21impl<'a> SpanBottomUpRef<'a> {
22 pub fn id(&self) -> SpanId {
23 unsafe { SpanId::new_unchecked((self.bottom_up.example_span.get() << 1) | 1) }
24 }
25
26 fn first_span(&self) -> SpanRef<'a> {
27 let index = self.bottom_up.self_spans[0].get();
28 SpanRef {
29 span: &self.store.spans[index],
30 store: self.store,
31 index,
32 }
33 }
34
35 fn example_span(&self) -> SpanRef<'a> {
36 let index = self.bottom_up.example_span.get();
37 SpanRef {
38 span: &self.store.spans[index],
39 store: self.store,
40 index,
41 }
42 }
43
44 pub fn spans(&self) -> impl Iterator<Item = SpanRef<'a>> + '_ {
45 let store = self.store;
46 self.bottom_up.self_spans.iter().map(move |span| SpanRef {
47 span: &store.spans[span.get()],
48 store,
49 index: span.get(),
50 })
51 }
52
53 pub fn count(&self) -> usize {
54 self.bottom_up.self_spans.len()
55 }
56
57 pub fn group_name(&self) -> &'a str {
58 self.first_span().group_name()
59 }
60
61 pub fn nice_name(&self) -> (&'a str, &'a str) {
62 if self.count() == 1 {
63 self.example_span().nice_name()
64 } else {
65 ("", self.example_span().group_name())
66 }
67 }
68
69 pub fn children(&self) -> impl Iterator<Item = SpanBottomUpRef<'a>> + '_ {
70 self.bottom_up
71 .children
72 .iter()
73 .map(|bottom_up| SpanBottomUpRef {
74 bottom_up: bottom_up.clone(),
75 store: self.store,
76 })
77 }
78
79 #[allow(dead_code)]
80 pub fn graph(&self) -> impl Iterator<Item = SpanGraphEventRef<'a>> + '_ {
81 self.bottom_up
82 .events
83 .get_or_init(|| {
84 if self.count() == 1 {
85 let _ = self.first_span().graph();
86 self.first_span().extra().graph.get().unwrap().clone()
87 } else {
88 let mut map: FxIndexMap<&str, (Vec<SpanIndex>, Vec<SpanIndex>)> =
89 FxIndexMap::default();
90 let mut queue = VecDeque::with_capacity(8);
91 for child in self.spans() {
92 let name = child.group_name();
93 let (list, recursive_list) = map.entry(name).or_default();
94 list.push(child.index());
95 queue.push_back(child);
96 while let Some(child) = queue.pop_front() {
97 for nested_child in child.children() {
98 let nested_name = nested_child.group_name();
99 if name == nested_name {
100 recursive_list.push(nested_child.index());
101 queue.push_back(nested_child);
102 }
103 }
104 }
105 }
106 event_map_to_list(map)
107 }
108 })
109 .iter()
110 .map(|graph| match graph {
111 SpanGraphEvent::SelfTime { duration } => SpanGraphEventRef::SelfTime {
112 duration: *duration,
113 },
114 SpanGraphEvent::Child { child } => SpanGraphEventRef::Child {
115 graph: SpanGraphRef {
116 graph: child.clone(),
117 store: self.store,
118 },
119 },
120 })
121 }
122
123 pub fn max_depth(&self) -> u32 {
124 *self.bottom_up.max_depth.get_or_init(|| {
125 self.children()
126 .map(|bottom_up| bottom_up.max_depth() + 1)
127 .max()
128 .unwrap_or(0)
129 })
130 }
131
132 pub fn corrected_self_time(&self) -> Timestamp {
133 *self
134 .bottom_up
135 .corrected_self_time
136 .get_or_init(|| self.spans().map(|span| span.corrected_self_time()).sum())
137 }
138
139 pub fn self_time(&self) -> Timestamp {
140 *self
141 .bottom_up
142 .self_time
143 .get_or_init(|| self.spans().map(|span| span.self_time()).sum())
144 }
145
146 pub fn self_allocations(&self) -> u64 {
147 *self
148 .bottom_up
149 .self_allocations
150 .get_or_init(|| self.spans().map(|span| span.self_allocations()).sum())
151 }
152
153 pub fn self_deallocations(&self) -> u64 {
154 *self
155 .bottom_up
156 .self_deallocations
157 .get_or_init(|| self.spans().map(|span| span.self_deallocations()).sum())
158 }
159
160 pub fn self_persistent_allocations(&self) -> u64 {
161 *self.bottom_up.self_persistent_allocations.get_or_init(|| {
162 self.spans()
163 .map(|span| span.self_persistent_allocations())
164 .sum()
165 })
166 }
167
168 pub fn self_allocation_count(&self) -> u64 {
169 *self
170 .bottom_up
171 .self_allocation_count
172 .get_or_init(|| self.spans().map(|span| span.self_allocation_count()).sum())
173 }
174
175 pub fn self_span_count(&self) -> u64 {
176 self.bottom_up.self_spans.len() as u64
177 }
178}
179
180impl Debug for SpanBottomUpRef<'_> {
181 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
182 f.debug_struct("SpanBottomUpRef")
183 .field("group_name", &self.group_name())
184 .field("max_depth", &self.max_depth())
185 .field("corrected_self_time", &self.corrected_self_time())
186 .field("self_allocations", &self.self_allocations())
187 .field("self_deallocations", &self.self_deallocations())
188 .field(
189 "self_persistent_allocations",
190 &self.self_persistent_allocations(),
191 )
192 .field("self_allocation_count", &self.self_allocation_count())
193 .finish()
194 }
195}