1use crate::{AnchorId, Key, ScopeId};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
6pub struct SlotTableLocalDebugStats {
7 pub group_count: usize,
9 pub group_capacity: usize,
11 pub group_record_size: usize,
13 pub group_heap_bytes: usize,
15 pub payload_count: usize,
17 pub payload_capacity: usize,
19 pub active_payload_anchor_count: usize,
21 pub payload_anchor_slot_count: usize,
23 pub detached_payload_anchor_count: usize,
25 pub invalidated_payload_anchor_count: usize,
27 pub free_payload_anchor_count: usize,
29 pub payload_anchor_capacity: usize,
31 pub payload_anchor_heap_bytes: usize,
33 pub node_count: usize,
35 pub node_capacity: usize,
37 pub active_anchor_count: usize,
39 pub anchor_slot_count: usize,
41 pub anchor_sparse_count: usize,
43 pub detached_anchor_count: usize,
45 pub invalidated_anchor_count: usize,
47 pub free_anchor_count: usize,
49 pub anchor_capacity: usize,
51 pub anchor_heap_bytes: usize,
53 #[cfg(any(test, feature = "leak-debug"))]
55 pub mutation: SlotTableMutationDebugStats,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
59pub(crate) struct SlotLifecycleDebugStats {
60 pub pending_drop_count: usize,
61 pub pending_drop_capacity: usize,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
67pub struct SlotRetentionDebugStats {
68 pub retained_subtree_count: usize,
70 pub retained_group_count: usize,
72 pub retained_payload_count: usize,
74 pub retained_node_count: usize,
76 pub retained_scope_count: usize,
78 pub retained_anchor_count: usize,
80 pub retained_heap_bytes: usize,
82 pub retained_evictions_total: usize,
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
90pub struct SlotTableDebugStats {
91 pub group_count: usize,
93 pub group_capacity: usize,
95 pub group_record_size: usize,
97 pub group_heap_bytes: usize,
99 pub payload_count: usize,
101 pub payload_capacity: usize,
103 pub active_payload_anchor_count: usize,
105 pub payload_anchor_slot_count: usize,
107 pub detached_payload_anchor_count: usize,
109 pub invalidated_payload_anchor_count: usize,
111 pub free_payload_anchor_count: usize,
113 pub payload_anchor_capacity: usize,
115 pub payload_anchor_heap_bytes: usize,
117 pub node_count: usize,
119 pub node_capacity: usize,
121 pub pending_drop_count: usize,
123 pub pending_drop_capacity: usize,
125 pub active_anchor_count: usize,
127 pub anchor_slot_count: usize,
129 pub anchor_sparse_count: usize,
131 pub detached_anchor_count: usize,
133 pub invalidated_anchor_count: usize,
135 pub free_anchor_count: usize,
137 pub anchor_capacity: usize,
139 pub anchor_heap_bytes: usize,
141 pub retained_subtree_count: usize,
143 pub retained_group_count: usize,
145 pub retained_payload_count: usize,
147 pub retained_node_count: usize,
149 pub retained_scope_count: usize,
151 pub retained_anchor_count: usize,
153 pub retained_heap_bytes: usize,
155 pub retained_evictions_total: usize,
157 #[cfg(any(test, feature = "leak-debug"))]
159 pub mutation: SlotTableMutationDebugStats,
160}
161
162impl SlotTableDebugStats {
163 pub(crate) fn from_parts(
164 local: SlotTableLocalDebugStats,
165 lifecycle: SlotLifecycleDebugStats,
166 retention: SlotRetentionDebugStats,
167 ) -> Self {
168 Self {
169 group_count: local.group_count,
170 group_capacity: local.group_capacity,
171 group_record_size: local.group_record_size,
172 group_heap_bytes: local.group_heap_bytes,
173 payload_count: local.payload_count,
174 payload_capacity: local.payload_capacity,
175 active_payload_anchor_count: local.active_payload_anchor_count,
176 payload_anchor_slot_count: local.payload_anchor_slot_count,
177 detached_payload_anchor_count: local.detached_payload_anchor_count,
178 invalidated_payload_anchor_count: local.invalidated_payload_anchor_count,
179 free_payload_anchor_count: local.free_payload_anchor_count,
180 payload_anchor_capacity: local.payload_anchor_capacity,
181 payload_anchor_heap_bytes: local.payload_anchor_heap_bytes,
182 node_count: local.node_count,
183 node_capacity: local.node_capacity,
184 pending_drop_count: lifecycle.pending_drop_count,
185 pending_drop_capacity: lifecycle.pending_drop_capacity,
186 active_anchor_count: local.active_anchor_count,
187 anchor_slot_count: local.anchor_slot_count,
188 anchor_sparse_count: local.anchor_sparse_count,
189 detached_anchor_count: local.detached_anchor_count,
190 invalidated_anchor_count: local.invalidated_anchor_count,
191 free_anchor_count: local.free_anchor_count,
192 anchor_capacity: local.anchor_capacity,
193 anchor_heap_bytes: local.anchor_heap_bytes,
194 retained_subtree_count: retention.retained_subtree_count,
195 retained_group_count: retention.retained_group_count,
196 retained_payload_count: retention.retained_payload_count,
197 retained_node_count: retention.retained_node_count,
198 retained_scope_count: retention.retained_scope_count,
199 retained_anchor_count: retention.retained_anchor_count,
200 retained_heap_bytes: retention.retained_heap_bytes,
201 retained_evictions_total: retention.retained_evictions_total,
202 #[cfg(any(test, feature = "leak-debug"))]
203 mutation: local.mutation,
204 }
205 }
206}
207
208#[cfg(any(test, feature = "leak-debug"))]
212#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
213pub struct SlotTableMutationDebugStats {
214 pub subtree_move_count: usize,
216 pub moved_group_count: usize,
218 pub moved_group_max_span: usize,
220 pub moved_payload_count: usize,
222 pub moved_payload_max_span: usize,
224 pub moved_node_count: usize,
226 pub moved_node_max_span: usize,
228 pub payload_location_range_refresh_count: usize,
230 pub payload_location_range_refresh_group_count: usize,
232 pub payload_location_range_refresh_group_max_span: usize,
234 pub payload_location_range_refresh_payload_count: usize,
236 pub payload_location_range_refresh_payload_max_span: usize,
238 pub payload_location_refresh_count: usize,
240 pub payload_location_refresh_payload_count: usize,
242 pub payload_location_refresh_max_span: usize,
244 pub group_index_refresh_count: usize,
246 pub group_index_refresh_group_count: usize,
248 pub group_index_refresh_max_span: usize,
250 pub segment_range_update_count: usize,
252 pub segment_range_update_group_count: usize,
254 pub segment_range_update_max_span: usize,
256 pub payload_shift_bytes: usize,
259}
260
261#[cfg(any(test, feature = "leak-debug"))]
264pub(crate) type SlotTableDiagnostics = SlotTableMutationDebugStats;
265
266#[cfg(not(any(test, feature = "leak-debug")))]
267#[derive(Default)]
268pub(crate) struct SlotTableDiagnostics;
269
270#[cfg(not(any(test, feature = "leak-debug")))]
271impl SlotTableDiagnostics {
272 pub(crate) fn record_subtree_move(&mut self, _groups: usize, _payloads: usize, _nodes: usize) {}
273
274 pub(crate) fn record_payload_location_range_refresh(
275 &mut self,
276 _groups: usize,
277 _payloads: usize,
278 ) {
279 }
280
281 pub(crate) fn record_group_index_refresh(&mut self, _groups: usize) {}
282
283 pub(crate) fn record_payload_location_refresh(&mut self, _payloads: usize) {}
284
285 pub(crate) fn record_segment_range_update(&mut self, _groups: usize) {}
286}
287
288#[cfg(any(test, feature = "leak-debug"))]
289impl SlotTableMutationDebugStats {
290 pub(crate) fn record_subtree_move(
291 &mut self,
292 group_span: usize,
293 payload_span: usize,
294 node_span: usize,
295 ) {
296 self.subtree_move_count = self.subtree_move_count.saturating_add(1);
297 self.moved_group_count = self.moved_group_count.saturating_add(group_span);
298 self.moved_group_max_span = self.moved_group_max_span.max(group_span);
299 self.moved_payload_count = self.moved_payload_count.saturating_add(payload_span);
300 self.moved_payload_max_span = self.moved_payload_max_span.max(payload_span);
301 self.moved_node_count = self.moved_node_count.saturating_add(node_span);
302 self.moved_node_max_span = self.moved_node_max_span.max(node_span);
303 }
304
305 pub(crate) fn record_payload_location_range_refresh(
306 &mut self,
307 group_span: usize,
308 payload_span: usize,
309 ) {
310 self.payload_location_range_refresh_count =
311 self.payload_location_range_refresh_count.saturating_add(1);
312 self.payload_location_range_refresh_group_count = self
313 .payload_location_range_refresh_group_count
314 .saturating_add(group_span);
315 self.payload_location_range_refresh_group_max_span = self
316 .payload_location_range_refresh_group_max_span
317 .max(group_span);
318 self.payload_location_range_refresh_payload_count = self
319 .payload_location_range_refresh_payload_count
320 .saturating_add(payload_span);
321 self.payload_location_range_refresh_payload_max_span = self
322 .payload_location_range_refresh_payload_max_span
323 .max(payload_span);
324 }
325
326 pub(crate) fn record_group_index_refresh(&mut self, group_span: usize) {
327 self.group_index_refresh_count = self.group_index_refresh_count.saturating_add(1);
328 self.group_index_refresh_group_count = self
329 .group_index_refresh_group_count
330 .saturating_add(group_span);
331 self.group_index_refresh_max_span = self.group_index_refresh_max_span.max(group_span);
332 }
333
334 pub(crate) fn record_payload_location_refresh(&mut self, payload_span: usize) {
335 self.payload_location_refresh_count = self.payload_location_refresh_count.saturating_add(1);
336 self.payload_location_refresh_payload_count = self
337 .payload_location_refresh_payload_count
338 .saturating_add(payload_span);
339 self.payload_location_refresh_max_span =
340 self.payload_location_refresh_max_span.max(payload_span);
341 }
342
343 pub(crate) fn record_segment_range_update(&mut self, group_span: usize) {
344 self.segment_range_update_count = self.segment_range_update_count.saturating_add(1);
345 self.segment_range_update_group_count = self
346 .segment_range_update_group_count
347 .saturating_add(group_span);
348 self.segment_range_update_max_span = self.segment_range_update_max_span.max(group_span);
349 }
350}
351
352#[derive(Debug, Clone, Copy, PartialEq, Eq)]
354pub enum SlotDebugEntryKind {
355 Group,
357 Payload,
359 Node,
361}
362
363#[derive(Debug, Clone, PartialEq, Eq)]
365pub struct SlotDebugEntry {
366 pub kind: SlotDebugEntryKind,
368 pub path: String,
370 pub line: String,
372}
373
374#[derive(Debug, Clone, PartialEq, Eq, Default)]
376pub struct SlotDebugSnapshot {
377 pub active_groups: Vec<SlotDebugGroup>,
379 pub anchors: Vec<SlotDebugAnchor>,
381 pub scopes: Vec<SlotDebugScope>,
383 pub active_payload_count: usize,
385 pub active_node_count: usize,
387 pub active_scope_count: usize,
389 pub retained_subtree_count: usize,
391 pub retained_group_count: usize,
393 pub retained_payload_count: usize,
395 pub retained_node_count: usize,
397 pub retained_scope_count: usize,
399}
400
401#[derive(Debug, Clone, Copy, PartialEq, Eq)]
403pub struct SlotDebugGroup {
404 pub index: usize,
406 pub anchor: AnchorId,
408 pub parent_anchor: AnchorId,
410 pub static_key: Key,
412 pub explicit_key: Option<Key>,
414 pub ordinal: u32,
417 pub scope_id: Option<ScopeId>,
419 pub depth: u32,
421 pub subtree_len: u32,
423 pub payload_len: usize,
425 pub node_len: usize,
427 pub subtree_node_count: u32,
429}
430
431#[derive(Debug, Clone, Copy, PartialEq, Eq)]
433pub struct SlotDebugAnchor {
434 pub anchor: AnchorId,
436 pub group_index: usize,
438}
439
440#[derive(Debug, Clone, Copy, PartialEq, Eq)]
442pub struct SlotDebugScope {
443 pub scope_id: ScopeId,
445 pub anchor: AnchorId,
447 pub group_index: usize,
449}