Skip to main content

cranpose_core/slot/
introspection.rs

1use super::{
2    GroupRecord, SlotDebugAnchor, SlotDebugEntry, SlotDebugEntryKind, SlotDebugGroup,
3    SlotDebugScope, SlotDebugSnapshot, SlotTable, SlotTableLocalDebugStats,
4};
5use crate::{Key, ScopeId};
6use std::mem;
7
8impl SlotTable {
9    fn group_heap_bytes(&self) -> usize {
10        self.groups.capacity() * mem::size_of::<GroupRecord>()
11    }
12
13    pub fn heap_bytes(&self) -> usize {
14        self.group_heap_bytes()
15            + self.payload_heap_bytes()
16            + self.node_heap_bytes()
17            + self.anchors.heap_bytes()
18            + self.payload_anchors.heap_bytes()
19            + self.scope_index.heap_bytes()
20    }
21
22    pub fn debug_stats(&self) -> SlotTableLocalDebugStats {
23        SlotTableLocalDebugStats {
24            group_count: self.groups.len(),
25            group_capacity: self.groups.capacity(),
26            group_record_size: mem::size_of::<GroupRecord>(),
27            group_heap_bytes: self.group_heap_bytes(),
28            payload_count: self.total_payload_count(),
29            payload_capacity: self.payload_debug_capacity(),
30            active_payload_anchor_count: self.payload_anchors.active_len(),
31            payload_anchor_slot_count: self.payload_anchors.slot_len(),
32            detached_payload_anchor_count: self.payload_anchors.detached_len(),
33            invalidated_payload_anchor_count: self.payload_anchors.invalidated_len(),
34            free_payload_anchor_count: self.payload_anchors.free_len(),
35            payload_anchor_capacity: self.payload_anchors.capacity(),
36            payload_anchor_heap_bytes: self.payload_anchors.heap_bytes(),
37            node_count: self.total_node_count(),
38            node_capacity: self.node_debug_capacity(),
39            active_anchor_count: self.anchors.active_len(),
40            anchor_slot_count: self.anchors.slot_len(),
41            anchor_sparse_count: self.anchors.sparse_slot_len(),
42            detached_anchor_count: self.anchors.detached_len(),
43            invalidated_anchor_count: self.anchors.invalidated_len(),
44            free_anchor_count: self.anchors.free_len(),
45            anchor_capacity: self.anchors.capacity(),
46            anchor_heap_bytes: self.anchors.heap_bytes(),
47            scope_index_count: self.scope_index.len(),
48            scope_index_capacity: self.scope_index.capacity(),
49            mutation: self.diagnostics.mutation(),
50        }
51    }
52
53    pub fn debug_dump_groups(&self) -> Vec<(usize, Key, Option<ScopeId>, usize)> {
54        self.groups
55            .iter()
56            .enumerate()
57            .map(|(index, group)| {
58                (
59                    index,
60                    group.key.static_key,
61                    group.scope_id,
62                    group.subtree_len as usize,
63                )
64            })
65            .collect()
66    }
67
68    pub fn debug_snapshot(&self) -> SlotDebugSnapshot {
69        let active_groups = self
70            .groups
71            .iter()
72            .enumerate()
73            .map(|(index, group)| SlotDebugGroup {
74                index,
75                anchor: group.anchor,
76                parent_anchor: group.parent_anchor,
77                static_key: group.key.static_key,
78                explicit_key: group.key.explicit_key,
79                ordinal: group.key.ordinal,
80                scope_id: group.scope_id,
81                depth: group.depth,
82                subtree_len: group.subtree_len,
83                payload_len: self.group_payload_len_at(index),
84                node_len: self.group_node_len_at(index),
85                subtree_node_count: group.subtree_node_count,
86            })
87            .collect::<Vec<_>>();
88        let mut anchors = self
89            .anchors
90            .active_entries()
91            .map(|(anchor, group_index)| SlotDebugAnchor {
92                anchor,
93                group_index,
94            })
95            .collect::<Vec<_>>();
96        anchors.sort_by_key(|entry| entry.group_index);
97
98        let mut scopes = self
99            .scope_index
100            .entries()
101            .filter_map(|(scope_id, anchor)| {
102                self.anchors
103                    .active_index(anchor)
104                    .map(|group_index| SlotDebugScope {
105                        scope_id,
106                        anchor,
107                        group_index,
108                    })
109            })
110            .collect::<Vec<_>>();
111        scopes.sort_by_key(|entry| entry.scope_id);
112
113        SlotDebugSnapshot {
114            active_payload_count: self.total_payload_count(),
115            active_node_count: self.total_node_count(),
116            active_scope_count: scopes.len(),
117            scope_index_count: self.scope_index.len(),
118            runtime_scope_registry_count: None,
119            active_groups,
120            anchors,
121            scopes,
122            retained_subtree_count: 0,
123            retained_group_count: 0,
124            retained_payload_count: 0,
125            retained_node_count: 0,
126            retained_scope_count: 0,
127        }
128    }
129
130    pub fn debug_dump_slot_entries(&self) -> Vec<SlotDebugEntry> {
131        let mut rows = Vec::new();
132        for (index, group) in self.groups.iter().enumerate() {
133            rows.push(SlotDebugEntry {
134                kind: SlotDebugEntryKind::Group,
135                path: format!("group[{index}]"),
136                line: format!(
137                    "Group(key={:?}, scope={:?}, subtree_len={}, payload_len={}, node_len={})",
138                    group.key,
139                    group.scope_id,
140                    group.subtree_len,
141                    self.group_payload_len_at(index),
142                    self.group_node_len_at(index)
143                ),
144            });
145        }
146        for (group_index, _) in self.groups.iter().enumerate() {
147            for (payload_index, payload) in self
148                .group_payload_records_at(group_index)
149                .iter()
150                .enumerate()
151            {
152                rows.push(SlotDebugEntry {
153                    kind: SlotDebugEntryKind::Payload,
154                    path: format!("group[{group_index}].payload[{payload_index}]"),
155                    line: format!(
156                        "Payload(owner={:?}, kind={}, type={})",
157                        payload.owner,
158                        payload.kind.label(),
159                        payload.type_name
160                    ),
161                });
162            }
163        }
164        for (group_index, _) in self.groups.iter().enumerate() {
165            for (node_index, node) in self.group_node_records_at(group_index).iter().enumerate() {
166                rows.push(SlotDebugEntry {
167                    kind: SlotDebugEntryKind::Node,
168                    path: format!("group[{group_index}].node[{node_index}]"),
169                    line: format!(
170                        "Node(owner={:?}, parent={:?}, id={}, gen={}, lifecycle={:?})",
171                        node.owner, node.parent_id, node.id, node.generation, node.lifecycle
172                    ),
173                });
174            }
175        }
176        rows
177    }
178}