Skip to main content

cranpose_core/slot/
introspection.rs

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