@memlab/mcp-server 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -13
- package/bin/memlab-mcp.js +9 -0
- package/dist/heap-state.d.ts +12 -1
- package/dist/heap-state.d.ts.map +1 -1
- package/dist/heap-state.js +10 -4
- package/dist/heap-state.js.map +1 -1
- package/dist/index.js +29 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/aggregate-nodes.d.ts.map +1 -1
- package/dist/tools/aggregate-nodes.js +2 -2
- package/dist/tools/aggregate-nodes.js.map +1 -1
- package/dist/tools/auto-investigate.d.ts +12 -0
- package/dist/tools/auto-investigate.d.ts.map +1 -0
- package/dist/tools/auto-investigate.js +683 -0
- package/dist/tools/auto-investigate.js.map +1 -0
- package/dist/tools/cache-analysis.d.ts +12 -0
- package/dist/tools/cache-analysis.d.ts.map +1 -0
- package/dist/tools/cache-analysis.js +341 -0
- package/dist/tools/cache-analysis.js.map +1 -0
- package/dist/tools/check-health.d.ts +12 -0
- package/dist/tools/check-health.d.ts.map +1 -0
- package/dist/tools/check-health.js +289 -0
- package/dist/tools/check-health.js.map +1 -0
- package/dist/tools/class-histogram.d.ts.map +1 -1
- package/dist/tools/class-histogram.js +70 -14
- package/dist/tools/class-histogram.js.map +1 -1
- package/dist/tools/closure-inspection.d.ts.map +1 -1
- package/dist/tools/closure-inspection.js +5 -5
- package/dist/tools/closure-inspection.js.map +1 -1
- package/dist/tools/detached-dom.d.ts.map +1 -1
- package/dist/tools/detached-dom.js +151 -5
- package/dist/tools/detached-dom.js.map +1 -1
- package/dist/tools/diff-snapshots.d.ts +12 -0
- package/dist/tools/diff-snapshots.d.ts.map +1 -0
- package/dist/tools/diff-snapshots.js +224 -0
- package/dist/tools/diff-snapshots.js.map +1 -0
- package/dist/tools/dominator-subtree.d.ts.map +1 -1
- package/dist/tools/dominator-subtree.js +29 -4
- package/dist/tools/dominator-subtree.js.map +1 -1
- package/dist/tools/duplicated-strings.d.ts.map +1 -1
- package/dist/tools/duplicated-strings.js +62 -9
- package/dist/tools/duplicated-strings.js.map +1 -1
- package/dist/tools/eval.d.ts.map +1 -1
- package/dist/tools/eval.js +111 -7
- package/dist/tools/eval.js.map +1 -1
- package/dist/tools/event-listener-leaks.d.ts +12 -0
- package/dist/tools/event-listener-leaks.d.ts.map +1 -0
- package/dist/tools/event-listener-leaks.js +266 -0
- package/dist/tools/event-listener-leaks.js.map +1 -0
- package/dist/tools/find-by-property.d.ts.map +1 -1
- package/dist/tools/find-by-property.js +38 -4
- package/dist/tools/find-by-property.js.map +1 -1
- package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
- package/dist/tools/find-nodes-by-class.js +4 -4
- package/dist/tools/find-nodes-by-class.js.map +1 -1
- package/dist/tools/for-each.d.ts.map +1 -1
- package/dist/tools/for-each.js +2 -2
- package/dist/tools/for-each.js.map +1 -1
- package/dist/tools/get-node.d.ts.map +1 -1
- package/dist/tools/get-node.js +2 -2
- package/dist/tools/get-node.js.map +1 -1
- package/dist/tools/get-property.d.ts.map +1 -1
- package/dist/tools/get-property.js +4 -4
- package/dist/tools/get-property.js.map +1 -1
- package/dist/tools/get-references.d.ts.map +1 -1
- package/dist/tools/get-references.js +11 -5
- package/dist/tools/get-references.js.map +1 -1
- package/dist/tools/get-referrers.d.ts.map +1 -1
- package/dist/tools/get-referrers.js +11 -5
- package/dist/tools/get-referrers.js.map +1 -1
- package/dist/tools/global-variables.d.ts.map +1 -1
- package/dist/tools/global-variables.js +10 -6
- package/dist/tools/global-variables.js.map +1 -1
- package/dist/tools/largest-objects.d.ts.map +1 -1
- package/dist/tools/largest-objects.js +78 -8
- package/dist/tools/largest-objects.js.map +1 -1
- package/dist/tools/load-snapshot.d.ts.map +1 -1
- package/dist/tools/load-snapshot.js +118 -4
- package/dist/tools/load-snapshot.js.map +1 -1
- package/dist/tools/object-shape.d.ts.map +1 -1
- package/dist/tools/object-shape.js +66 -47
- package/dist/tools/object-shape.js.map +1 -1
- package/dist/tools/pinch-points.d.ts +12 -0
- package/dist/tools/pinch-points.d.ts.map +1 -0
- package/dist/tools/pinch-points.js +124 -0
- package/dist/tools/pinch-points.js.map +1 -0
- package/dist/tools/quick-diagnosis.d.ts +12 -0
- package/dist/tools/quick-diagnosis.d.ts.map +1 -0
- package/dist/tools/quick-diagnosis.js +213 -0
- package/dist/tools/quick-diagnosis.js.map +1 -0
- package/dist/tools/referrer-summary.d.ts +12 -0
- package/dist/tools/referrer-summary.d.ts.map +1 -0
- package/dist/tools/referrer-summary.js +119 -0
- package/dist/tools/referrer-summary.js.map +1 -0
- package/dist/tools/reports.d.ts.map +1 -1
- package/dist/tools/reports.js +5 -5
- package/dist/tools/reports.js.map +1 -1
- package/dist/tools/retainer-summary.d.ts +12 -0
- package/dist/tools/retainer-summary.d.ts.map +1 -0
- package/dist/tools/retainer-summary.js +307 -0
- package/dist/tools/retainer-summary.js.map +1 -0
- package/dist/tools/retainer-trace.d.ts.map +1 -1
- package/dist/tools/retainer-trace.js +88 -14
- package/dist/tools/retainer-trace.js.map +1 -1
- package/dist/tools/search-nodes.d.ts.map +1 -1
- package/dist/tools/search-nodes.js +2 -2
- package/dist/tools/search-nodes.js.map +1 -1
- package/dist/tools/shape-histogram.d.ts +12 -0
- package/dist/tools/shape-histogram.d.ts.map +1 -0
- package/dist/tools/shape-histogram.js +119 -0
- package/dist/tools/shape-histogram.js.map +1 -0
- package/dist/tools/sliced-strings.d.ts +12 -0
- package/dist/tools/sliced-strings.d.ts.map +1 -0
- package/dist/tools/sliced-strings.js +126 -0
- package/dist/tools/sliced-strings.js.map +1 -0
- package/dist/tools/snapshot-summary.d.ts.map +1 -1
- package/dist/tools/snapshot-summary.js +42 -3
- package/dist/tools/snapshot-summary.js.map +1 -1
- package/dist/tools/stale-collections.d.ts.map +1 -1
- package/dist/tools/stale-collections.js +30 -6
- package/dist/tools/stale-collections.js.map +1 -1
- package/dist/tools/string-patterns.d.ts +12 -0
- package/dist/tools/string-patterns.d.ts.map +1 -0
- package/dist/tools/string-patterns.js +115 -0
- package/dist/tools/string-patterns.js.map +1 -0
- package/dist/tools/trace-dominators.d.ts +12 -0
- package/dist/tools/trace-dominators.d.ts.map +1 -0
- package/dist/tools/trace-dominators.js +237 -0
- package/dist/tools/trace-dominators.js.map +1 -0
- package/dist/utils.d.ts +9 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +67 -5
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { getSnapshot } from '../heap-state.js';
|
|
12
|
+
import { filterLargestObjects, formatBytes, errorResult, toolResult, } from '../utils.js';
|
|
13
|
+
const FRAMEWORK_PATTERNS = new Set([
|
|
14
|
+
'system / Context',
|
|
15
|
+
'system / PromiseReaction',
|
|
16
|
+
'system / NativeContext',
|
|
17
|
+
'system / ScriptContext',
|
|
18
|
+
'system / FunctionContext',
|
|
19
|
+
'system / BlockContext',
|
|
20
|
+
'system / CatchContext',
|
|
21
|
+
'system / WithContext',
|
|
22
|
+
'system / EvalContext',
|
|
23
|
+
'system / ModuleContext',
|
|
24
|
+
'system / Oddball',
|
|
25
|
+
'(GC roots)',
|
|
26
|
+
'(Strong roots)',
|
|
27
|
+
'(Builtins)',
|
|
28
|
+
'(Startup object cache)',
|
|
29
|
+
]);
|
|
30
|
+
function isFrameworkStep(step) {
|
|
31
|
+
if (FRAMEWORK_PATTERNS.has(step.name))
|
|
32
|
+
return true;
|
|
33
|
+
if (step.name.startsWith('system / '))
|
|
34
|
+
return true;
|
|
35
|
+
if (step.type === 'hidden' || step.type === 'synthetic')
|
|
36
|
+
return true;
|
|
37
|
+
if (step.name === 'require' && step.type === 'closure')
|
|
38
|
+
return true;
|
|
39
|
+
if (step.edgeName === 'cache' && step.name === 'Object')
|
|
40
|
+
return true;
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
function getRetainerTrace(node) {
|
|
44
|
+
if (!node.hasPathEdge)
|
|
45
|
+
return null;
|
|
46
|
+
const visited = new Set([node.id]);
|
|
47
|
+
let curNode = node;
|
|
48
|
+
const reverseSteps = [{ name: curNode.name, type: curNode.type }];
|
|
49
|
+
while (curNode && curNode.hasPathEdge) {
|
|
50
|
+
const edge = curNode.pathEdge;
|
|
51
|
+
if (!edge)
|
|
52
|
+
break;
|
|
53
|
+
const fromNode = edge.fromNode;
|
|
54
|
+
if (visited.has(fromNode.id))
|
|
55
|
+
break;
|
|
56
|
+
visited.add(fromNode.id);
|
|
57
|
+
reverseSteps.push({
|
|
58
|
+
name: fromNode.name,
|
|
59
|
+
type: fromNode.type,
|
|
60
|
+
edgeName: String(edge.name_or_index),
|
|
61
|
+
});
|
|
62
|
+
curNode = fromNode;
|
|
63
|
+
}
|
|
64
|
+
reverseSteps.reverse();
|
|
65
|
+
return reverseSteps;
|
|
66
|
+
}
|
|
67
|
+
function normalizeEdgeName(name) {
|
|
68
|
+
return /^\d+$/.test(name) ? '*' : name;
|
|
69
|
+
}
|
|
70
|
+
function traceToKey(steps, frameworkFilter) {
|
|
71
|
+
const filtered = frameworkFilter
|
|
72
|
+
? steps.filter((s, i) => i === 0 || i === steps.length - 1 || !isFrameworkStep(s))
|
|
73
|
+
: steps;
|
|
74
|
+
return filtered
|
|
75
|
+
.map(s => {
|
|
76
|
+
const edge = s.edgeName != null ? `--${normalizeEdgeName(s.edgeName)}-->` : '';
|
|
77
|
+
return `${s.name}(${s.type})${edge}`;
|
|
78
|
+
})
|
|
79
|
+
.join(' ');
|
|
80
|
+
}
|
|
81
|
+
function shortenPath(name) {
|
|
82
|
+
if (name.length <= 40)
|
|
83
|
+
return name;
|
|
84
|
+
const parts = name.split('/');
|
|
85
|
+
if (parts.length <= 2)
|
|
86
|
+
return name;
|
|
87
|
+
const fileName = parts[parts.length - 1];
|
|
88
|
+
const dir = parts[parts.length - 2];
|
|
89
|
+
return `…/${dir}/${fileName}`;
|
|
90
|
+
}
|
|
91
|
+
function formatTraceChain(steps) {
|
|
92
|
+
const parts = [];
|
|
93
|
+
for (let i = 0; i < steps.length; i++) {
|
|
94
|
+
const s = steps[i];
|
|
95
|
+
parts.push(`${s.name} (${s.type})`);
|
|
96
|
+
if (s.edgeName != null && i < steps.length - 1) {
|
|
97
|
+
parts.push(` --${s.edgeName}--> `);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return parts.join('');
|
|
101
|
+
}
|
|
102
|
+
function formatTraceChainCompact(steps, frameworkFilter) {
|
|
103
|
+
const filtered = frameworkFilter
|
|
104
|
+
? steps.filter((s, i) => i === 0 || i === steps.length - 1 || !isFrameworkStep(s))
|
|
105
|
+
: steps;
|
|
106
|
+
const parts = [];
|
|
107
|
+
for (let i = 0; i < filtered.length; i++) {
|
|
108
|
+
const s = filtered[i];
|
|
109
|
+
const name = shortenPath(s.name);
|
|
110
|
+
if (i === 0 || i === filtered.length - 1) {
|
|
111
|
+
const suffix = s.type === 'closure' ? '()' : '';
|
|
112
|
+
parts.push(`${name}${suffix}`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
parts.push(name);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return parts.join(' → ');
|
|
119
|
+
}
|
|
120
|
+
export function registerRetainerSummary(server) {
|
|
121
|
+
server.tool('memlab_retainer_summary', 'Trace retainer paths for multiple instances of a class (or a specific set of node IDs) and group by common patterns. Instead of tracing one node at a time, this samples N instances and shows how many share each retainer path pattern. Essential for confirming whether leaked objects share a single root cause. Use node_ids to cluster retainer patterns for specific nodes (e.g., example_node_ids from duplicated_strings). Set compact=true for abbreviated paths that use 50-70% fewer tokens.', {
|
|
122
|
+
class_name: z
|
|
123
|
+
.string()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe('The constructor/class name to analyze. Supports exact match and substring match (e.g., "Detached <div>" will match V8\'s detached DOM naming). Required if node_ids and name_prefix are not provided.'),
|
|
126
|
+
name_prefix: z
|
|
127
|
+
.string()
|
|
128
|
+
.optional()
|
|
129
|
+
.describe('Match nodes whose name starts with this prefix (e.g., "Detached" matches all detached DOM nodes regardless of element type). Use instead of class_name when the exact name varies.'),
|
|
130
|
+
node_ids: z
|
|
131
|
+
.array(z.number())
|
|
132
|
+
.optional()
|
|
133
|
+
.describe('Specific node IDs to analyze instead of searching by class name. Use this with example_node_ids from duplicated_strings or other tools.'),
|
|
134
|
+
sample: z
|
|
135
|
+
.number()
|
|
136
|
+
.optional()
|
|
137
|
+
.default(10)
|
|
138
|
+
.describe('Number of instances to sample, picked from the largest by retained size (default 10). Only applies when using class_name.'),
|
|
139
|
+
max_depth: z
|
|
140
|
+
.number()
|
|
141
|
+
.optional()
|
|
142
|
+
.describe('Truncate each retainer trace to this many nodes from the GC root before grouping. Useful for grouping traces that diverge only in the last few hops.'),
|
|
143
|
+
compact: z
|
|
144
|
+
.boolean()
|
|
145
|
+
.optional()
|
|
146
|
+
.default(false)
|
|
147
|
+
.describe('Use compact retainer path format with abbreviated names and → arrows. Reduces token usage by 50-70%.'),
|
|
148
|
+
framework_filter: z
|
|
149
|
+
.boolean()
|
|
150
|
+
.optional()
|
|
151
|
+
.default(false)
|
|
152
|
+
.describe('Exclude known V8/Node.js framework internals (system / Context, PromiseReaction, module cache patterns) from retainer paths. Helps surface application-level retention.'),
|
|
153
|
+
}, async ({ class_name, name_prefix, node_ids, sample, max_depth, compact, framework_filter, }) => {
|
|
154
|
+
try {
|
|
155
|
+
const snapshot = getSnapshot();
|
|
156
|
+
let nodes;
|
|
157
|
+
let label;
|
|
158
|
+
if (node_ids && node_ids.length > 0) {
|
|
159
|
+
nodes = [];
|
|
160
|
+
for (const id of node_ids) {
|
|
161
|
+
const node = snapshot.getNodeById(id);
|
|
162
|
+
if (node)
|
|
163
|
+
nodes.push(node);
|
|
164
|
+
}
|
|
165
|
+
label = `${nodes.length} specified node(s)`;
|
|
166
|
+
}
|
|
167
|
+
else if (name_prefix) {
|
|
168
|
+
nodes = filterLargestObjects(snapshot, node => node.name.startsWith(name_prefix), sample);
|
|
169
|
+
label = `prefix "${name_prefix}"`;
|
|
170
|
+
}
|
|
171
|
+
else if (class_name) {
|
|
172
|
+
// Try exact match first
|
|
173
|
+
nodes = filterLargestObjects(snapshot, node => node.name === class_name, sample);
|
|
174
|
+
// Fall back to substring match (handles V8 detached DOM names
|
|
175
|
+
// like "Detached <div>" which contain angle brackets)
|
|
176
|
+
if (nodes.length === 0) {
|
|
177
|
+
nodes = filterLargestObjects(snapshot, node => node.name.includes(class_name), sample);
|
|
178
|
+
}
|
|
179
|
+
label = `"${class_name}"`;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
return errorResult(new Error('Either class_name, name_prefix, or node_ids must be provided.'));
|
|
183
|
+
}
|
|
184
|
+
if (nodes.length === 0) {
|
|
185
|
+
return toolResult(`No objects found for ${label}`);
|
|
186
|
+
}
|
|
187
|
+
const patterns = new Map();
|
|
188
|
+
let noTrace = 0;
|
|
189
|
+
let earlyStop = false;
|
|
190
|
+
const EARLY_STOP_THRESHOLD = 5;
|
|
191
|
+
for (let ni = 0; ni < nodes.length; ni++) {
|
|
192
|
+
const node = nodes[ni];
|
|
193
|
+
const trace = getRetainerTrace(node);
|
|
194
|
+
if (!trace) {
|
|
195
|
+
noTrace++;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const steps = max_depth != null && max_depth > 0 && max_depth < trace.length
|
|
199
|
+
? trace.slice(0, max_depth)
|
|
200
|
+
: trace;
|
|
201
|
+
const key = traceToKey(steps, framework_filter);
|
|
202
|
+
const existing = patterns.get(key);
|
|
203
|
+
if (existing) {
|
|
204
|
+
existing.count++;
|
|
205
|
+
if (existing.example_ids.length < 3) {
|
|
206
|
+
existing.example_ids.push(node.id);
|
|
207
|
+
}
|
|
208
|
+
existing.total_retained += node.retainedSize;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
patterns.set(key, {
|
|
212
|
+
steps,
|
|
213
|
+
count: 1,
|
|
214
|
+
example_ids: [node.id],
|
|
215
|
+
total_retained: node.retainedSize,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
const tracedSoFar = ni + 1 - noTrace;
|
|
219
|
+
if (tracedSoFar >= EARLY_STOP_THRESHOLD &&
|
|
220
|
+
patterns.size === 1 &&
|
|
221
|
+
ni < nodes.length - 1) {
|
|
222
|
+
earlyStop = true;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const sorted = [...patterns.values()].sort((a, b) => b.count - a.count);
|
|
227
|
+
const totalSampled = sorted.reduce((s, p) => s + p.count, 0) + noTrace;
|
|
228
|
+
const modifiers = [];
|
|
229
|
+
if (max_depth)
|
|
230
|
+
modifiers.push(`depth limited to ${max_depth}`);
|
|
231
|
+
if (compact)
|
|
232
|
+
modifiers.push('compact');
|
|
233
|
+
if (framework_filter)
|
|
234
|
+
modifiers.push('framework filtered');
|
|
235
|
+
if (earlyStop)
|
|
236
|
+
modifiers.push('early termination — high confidence');
|
|
237
|
+
const modStr = modifiers.length > 0 ? `, ${modifiers.join(', ')}` : '';
|
|
238
|
+
const lines = [
|
|
239
|
+
`Retainer summary for ${label} (${totalSampled} sampled${modStr})`,
|
|
240
|
+
'',
|
|
241
|
+
];
|
|
242
|
+
if (sorted.length === 1) {
|
|
243
|
+
const conf = earlyStop
|
|
244
|
+
? ' (early termination — all samples matched)'
|
|
245
|
+
: '';
|
|
246
|
+
lines.push(`**All ${sorted[0].count} sampled instances share the same retainer pattern** — likely a single root cause.${conf}`, '');
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
lines.push(`**${sorted.length} distinct retainer patterns found:**`, '');
|
|
250
|
+
}
|
|
251
|
+
const filterSteps = (steps) => framework_filter
|
|
252
|
+
? steps.filter((s, i) => i === 0 || i === steps.length - 1 || !isFrameworkStep(s))
|
|
253
|
+
: steps;
|
|
254
|
+
const formatFn = compact
|
|
255
|
+
? (steps) => formatTraceChainCompact(steps, framework_filter)
|
|
256
|
+
: (steps) => formatTraceChain(filterSteps(steps));
|
|
257
|
+
const getDisplaySteps = (p) => compact ? filterSteps(p.steps) : p.steps;
|
|
258
|
+
let commonPrefixLen = 0;
|
|
259
|
+
if (sorted.length > 1) {
|
|
260
|
+
const allSteps = sorted.map(getDisplaySteps);
|
|
261
|
+
const minLen = Math.min(...allSteps.map(s => s.length));
|
|
262
|
+
for (let ci = 0; ci < minLen - 1; ci++) {
|
|
263
|
+
const ref = allSteps[0][ci];
|
|
264
|
+
const refKey = `${ref.name}(${ref.type})${ref.edgeName ?? ''}`;
|
|
265
|
+
if (allSteps.every(s => {
|
|
266
|
+
const step = s[ci];
|
|
267
|
+
return (`${step.name}(${step.type})${step.edgeName ?? ''}` === refKey);
|
|
268
|
+
})) {
|
|
269
|
+
commonPrefixLen = ci + 1;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (commonPrefixLen >= 2) {
|
|
277
|
+
const prefixSteps = getDisplaySteps(sorted[0]).slice(0, commonPrefixLen);
|
|
278
|
+
lines.push(`**Common prefix** (${commonPrefixLen} nodes):`);
|
|
279
|
+
lines.push(formatFn(prefixSteps));
|
|
280
|
+
lines.push('');
|
|
281
|
+
}
|
|
282
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
283
|
+
const p = sorted[i];
|
|
284
|
+
const pct = ((p.count / totalSampled) * 100).toFixed(0);
|
|
285
|
+
lines.push(`### Pattern ${i + 1}: ${p.count}/${totalSampled} instances (${pct}%), ${formatBytes(p.total_retained)} retained`);
|
|
286
|
+
lines.push('');
|
|
287
|
+
const displaySteps = commonPrefixLen >= 2
|
|
288
|
+
? getDisplaySteps(p).slice(commonPrefixLen)
|
|
289
|
+
: p.steps;
|
|
290
|
+
lines.push(commonPrefixLen >= 2
|
|
291
|
+
? `… → ${formatFn(displaySteps)}`
|
|
292
|
+
: formatFn(displaySteps));
|
|
293
|
+
lines.push('');
|
|
294
|
+
lines.push(`Example nodes: ${p.example_ids.map(id => `@${id}`).join(', ')}`);
|
|
295
|
+
lines.push('');
|
|
296
|
+
}
|
|
297
|
+
if (noTrace > 0) {
|
|
298
|
+
lines.push(`(${noTrace} instance(s) had no retainer path — root or unreachable nodes)`);
|
|
299
|
+
}
|
|
300
|
+
return toolResult(lines.join('\n'));
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
return errorResult(err);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=retainer-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retainer-summary.js","sourceRoot":"","sources":["../../src/tools/retainer-summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retainer-trace.d.ts","sourceRoot":"","sources":["../../src/tools/retainer-trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"retainer-trace.d.ts","sourceRoot":"","sources":["../../src/tools/retainer-trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAavE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0K7D"}
|
|
@@ -9,11 +9,20 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { getSnapshot } from '../heap-state.js';
|
|
12
|
-
import { formatNodeInline, errorResult,
|
|
12
|
+
import { formatNodeInline, formatBytes, isNodeWorthInspecting, errorResult, toolResult, } from '../utils.js';
|
|
13
13
|
export function registerRetainerTrace(server) {
|
|
14
|
-
server.tool('memlab_retainer_trace', 'Get the shortest path from a GC root to a specific heap node. This shows why the object is retained in memory by walking the pathEdge chain.', {
|
|
14
|
+
server.tool('memlab_retainer_trace', 'Get the shortest path from a GC root to a specific heap node. This shows why the object is retained in memory by walking the pathEdge chain. Use memlab_retainer_summary to trace multiple instances of a class and group by common retainer patterns. Use memlab_get_referrers / memlab_get_references to explore incoming/outgoing edges from a node.', {
|
|
15
15
|
node_id: z.number().describe('The numeric ID of the heap node'),
|
|
16
|
-
|
|
16
|
+
max_depth: z
|
|
17
|
+
.number()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Maximum number of nodes in the trace. When set, shows only the first N nodes from the GC root. Useful for long traces where only the first few hops matter.'),
|
|
20
|
+
show_sizes: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.default(true)
|
|
24
|
+
.describe('Show retained size at each node in the trace (default true). Makes it easy to see where memory concentrates along the path.'),
|
|
25
|
+
}, async ({ node_id, max_depth, show_sizes }) => {
|
|
17
26
|
try {
|
|
18
27
|
const snapshot = getSnapshot();
|
|
19
28
|
const node = snapshot.getNodeById(node_id);
|
|
@@ -21,7 +30,7 @@ export function registerRetainerTrace(server) {
|
|
|
21
30
|
return errorResult(`Node with id ${node_id} not found`);
|
|
22
31
|
}
|
|
23
32
|
if (!node.hasPathEdge) {
|
|
24
|
-
return
|
|
33
|
+
return toolResult('No retainer path available for this node. It may be a root node or unreachable.');
|
|
25
34
|
}
|
|
26
35
|
const visited = new Set([node.id]);
|
|
27
36
|
let curNode = node;
|
|
@@ -44,21 +53,86 @@ export function registerRetainerTrace(server) {
|
|
|
44
53
|
}
|
|
45
54
|
// Reverse to get root-first order
|
|
46
55
|
reverseItems.reverse();
|
|
47
|
-
//
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
parts.push(` --${item.edgeName}--> `);
|
|
56
|
+
// Collapse consecutive internal/V8 nodes for readability
|
|
57
|
+
const collapsed = [];
|
|
58
|
+
let internalRun = 0;
|
|
59
|
+
for (const item of reverseItems) {
|
|
60
|
+
if (!isNodeWorthInspecting(item.node) && collapsed.length > 0) {
|
|
61
|
+
internalRun++;
|
|
54
62
|
}
|
|
63
|
+
else {
|
|
64
|
+
if (internalRun > 0) {
|
|
65
|
+
collapsed.push({
|
|
66
|
+
node: item.node,
|
|
67
|
+
edgeName: item.edgeName,
|
|
68
|
+
edgeType: item.edgeType,
|
|
69
|
+
collapsedCount: internalRun,
|
|
70
|
+
});
|
|
71
|
+
internalRun = 0;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
collapsed.push(item);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (internalRun > 0 && collapsed.length > 0) {
|
|
79
|
+
const last = collapsed[collapsed.length - 1];
|
|
80
|
+
last.collapsedCount = (last.collapsedCount ?? 0) + internalRun;
|
|
55
81
|
}
|
|
82
|
+
const fullLength = reverseItems.length;
|
|
83
|
+
const truncated = max_depth != null && max_depth > 0 && max_depth < fullLength;
|
|
84
|
+
const items = truncated ? collapsed.slice(0, max_depth) : collapsed;
|
|
85
|
+
const depthNote = truncated
|
|
86
|
+
? `, showing first ${max_depth} of ${fullLength}`
|
|
87
|
+
: '';
|
|
56
88
|
const lines = [
|
|
57
|
-
`Retainer trace for @${node_id} (${
|
|
89
|
+
`Retainer trace for @${node_id} (${fullLength} nodes${depthNote}):`,
|
|
58
90
|
'',
|
|
59
|
-
parts.join(''),
|
|
60
91
|
];
|
|
61
|
-
|
|
92
|
+
if (show_sizes) {
|
|
93
|
+
// Vertical format with sizes for readability
|
|
94
|
+
for (let i = 0; i < items.length; i++) {
|
|
95
|
+
const item = items[i];
|
|
96
|
+
const n = item.node;
|
|
97
|
+
const sizeStr = formatBytes(n.retainedSize);
|
|
98
|
+
const nodeStr = formatNodeInline(n.id, n.name, n.type, n.self_size);
|
|
99
|
+
if (item.collapsedCount && item.collapsedCount > 0) {
|
|
100
|
+
lines.push(` ← [${item.collapsedCount} internal node(s)] ←`);
|
|
101
|
+
}
|
|
102
|
+
if (i === 0) {
|
|
103
|
+
lines.push(`${nodeStr} [${sizeStr}]`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const prevItem = items[i - 1];
|
|
107
|
+
const edgeLabel = prevItem.edgeName ?? '?';
|
|
108
|
+
lines.push(` ← ${edgeLabel} ← ${nodeStr} [${sizeStr}]`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (truncated && max_depth != null) {
|
|
112
|
+
lines.push(` ← ... (${fullLength - max_depth} more nodes) ...`);
|
|
113
|
+
const target = reverseItems[reverseItems.length - 1];
|
|
114
|
+
const tn = target.node;
|
|
115
|
+
lines.push(` ← ${formatNodeInline(tn.id, tn.name, tn.type, tn.self_size)} [${formatBytes(tn.retainedSize)}]`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Compact inline chain format
|
|
120
|
+
const parts = [];
|
|
121
|
+
for (let i = 0; i < items.length; i++) {
|
|
122
|
+
const item = items[i];
|
|
123
|
+
parts.push(formatNodeInline(item.node.id, item.node.name, item.node.type, item.node.self_size));
|
|
124
|
+
if (item.edgeName != null && i < items.length - 1) {
|
|
125
|
+
parts.push(` --${item.edgeName}--> `);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (truncated && max_depth != null) {
|
|
129
|
+
parts.push(` --...--> (${fullLength - max_depth} more nodes) --...--> `);
|
|
130
|
+
const target = reverseItems[reverseItems.length - 1];
|
|
131
|
+
parts.push(formatNodeInline(target.node.id, target.node.name, target.node.type, target.node.self_size));
|
|
132
|
+
}
|
|
133
|
+
lines.push(parts.join(''));
|
|
134
|
+
}
|
|
135
|
+
return toolResult(lines.join('\n'));
|
|
62
136
|
}
|
|
63
137
|
catch (err) {
|
|
64
138
|
return errorResult(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retainer-trace.js","sourceRoot":"","sources":["../../src/tools/retainer-trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"retainer-trace.js","sourceRoot":"","sources":["../../src/tools/retainer-trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-nodes.d.ts","sourceRoot":"","sources":["../../src/tools/search-nodes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"search-nodes.d.ts","sourceRoot":"","sources":["../../src/tools/search-nodes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAavE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0F3D"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { getSnapshot } from '../heap-state.js';
|
|
12
|
-
import { queryNodes, formatQueryNodesResult, errorResult,
|
|
12
|
+
import { queryNodes, formatQueryNodesResult, errorResult, toolResult, } from '../utils.js';
|
|
13
13
|
export function registerSearchNodes(server) {
|
|
14
14
|
server.tool('memlab_search_nodes', 'General-purpose search for heap nodes by combining filters: name pattern (regex), node type, minimum retained/self size, and detachment status. Results sorted by retained size. Supports count-only and ids-only modes for large result sets.', {
|
|
15
15
|
name_pattern: z
|
|
@@ -75,7 +75,7 @@ export function registerSearchNodes(server) {
|
|
|
75
75
|
offset,
|
|
76
76
|
outputMode: output_mode,
|
|
77
77
|
});
|
|
78
|
-
return
|
|
78
|
+
return toolResult(formatQueryNodesResult(result, offset));
|
|
79
79
|
}
|
|
80
80
|
catch (err) {
|
|
81
81
|
return errorResult(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-nodes.js","sourceRoot":"","sources":["../../src/tools/search-nodes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,WAAW,
|
|
1
|
+
{"version":3,"file":"search-nodes.js","sourceRoot":"","sources":["../../src/tools/search-nodes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
+
export declare function registerShapeHistogram(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=shape-histogram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shape-histogram.d.ts","sourceRoot":"","sources":["../../src/tools/shape-histogram.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA4BvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+H9D"}
|