@memlab/mcp-server 2.1.0 → 2.3.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 +88 -3
- package/dist/analysis-budget.d.ts +71 -0
- package/dist/analysis-budget.d.ts.map +1 -0
- package/dist/analysis-budget.js +118 -0
- package/dist/analysis-budget.js.map +1 -0
- package/dist/guardrail.d.ts +24 -0
- package/dist/guardrail.d.ts.map +1 -0
- package/dist/guardrail.js +65 -0
- package/dist/guardrail.js.map +1 -0
- package/dist/heap-state.d.ts +46 -1
- package/dist/heap-state.d.ts.map +1 -1
- package/dist/heap-state.js +142 -10
- package/dist/heap-state.js.map +1 -1
- package/dist/index.js +36 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/array-group-by.d.ts +12 -0
- package/dist/tools/array-group-by.d.ts.map +1 -0
- package/dist/tools/array-group-by.js +191 -0
- package/dist/tools/array-group-by.js.map +1 -0
- package/dist/tools/auto-investigate.d.ts.map +1 -1
- package/dist/tools/auto-investigate.js +999 -37
- package/dist/tools/auto-investigate.js.map +1 -1
- package/dist/tools/cache-analysis.d.ts.map +1 -1
- package/dist/tools/cache-analysis.js +438 -21
- package/dist/tools/cache-analysis.js.map +1 -1
- package/dist/tools/check-health.d.ts.map +1 -1
- package/dist/tools/check-health.js +261 -1
- package/dist/tools/check-health.js.map +1 -1
- package/dist/tools/class-histogram.d.ts.map +1 -1
- package/dist/tools/class-histogram.js +142 -33
- 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 +238 -25
- 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 +25 -3
- package/dist/tools/detached-dom.js.map +1 -1
- package/dist/tools/dev-artifacts.d.ts +33 -0
- package/dist/tools/dev-artifacts.d.ts.map +1 -0
- package/dist/tools/dev-artifacts.js +165 -0
- package/dist/tools/dev-artifacts.js.map +1 -0
- package/dist/tools/diff-snapshots.d.ts.map +1 -1
- package/dist/tools/diff-snapshots.js +113 -18
- package/dist/tools/diff-snapshots.js.map +1 -1
- package/dist/tools/duplicated-strings.d.ts.map +1 -1
- package/dist/tools/duplicated-strings.js +74 -12
- package/dist/tools/duplicated-strings.js.map +1 -1
- package/dist/tools/eval.d.ts.map +1 -1
- package/dist/tools/eval.js +189 -10
- package/dist/tools/eval.js.map +1 -1
- package/dist/tools/event-listener-leaks.d.ts.map +1 -1
- package/dist/tools/event-listener-leaks.js +235 -13
- package/dist/tools/event-listener-leaks.js.map +1 -1
- package/dist/tools/event-registry.d.ts +12 -0
- package/dist/tools/event-registry.d.ts.map +1 -0
- package/dist/tools/event-registry.js +183 -0
- package/dist/tools/event-registry.js.map +1 -0
- package/dist/tools/find-by-property.d.ts.map +1 -1
- package/dist/tools/find-by-property.js +113 -31
- package/dist/tools/find-by-property.js.map +1 -1
- package/dist/tools/find-by-shape.d.ts +12 -0
- package/dist/tools/find-by-shape.d.ts.map +1 -0
- package/dist/tools/find-by-shape.js +178 -0
- package/dist/tools/find-by-shape.js.map +1 -0
- package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
- package/dist/tools/find-nodes-by-class.js +50 -6
- 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 +1 -1
- 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 +6 -0
- package/dist/tools/get-node.js.map +1 -1
- package/dist/tools/get-string.d.ts +12 -0
- package/dist/tools/get-string.d.ts.map +1 -0
- package/dist/tools/get-string.js +223 -0
- package/dist/tools/get-string.js.map +1 -0
- package/dist/tools/get-value.d.ts +12 -0
- package/dist/tools/get-value.d.ts.map +1 -0
- package/dist/tools/get-value.js +152 -0
- package/dist/tools/get-value.js.map +1 -0
- package/dist/tools/global-variables.d.ts.map +1 -1
- package/dist/tools/global-variables.js +54 -34
- package/dist/tools/global-variables.js.map +1 -1
- package/dist/tools/growth-signals.d.ts +12 -0
- package/dist/tools/growth-signals.d.ts.map +1 -0
- package/dist/tools/growth-signals.js +211 -0
- package/dist/tools/growth-signals.js.map +1 -0
- package/dist/tools/intern-opportunities.d.ts +12 -0
- package/dist/tools/intern-opportunities.d.ts.map +1 -0
- package/dist/tools/intern-opportunities.js +289 -0
- package/dist/tools/intern-opportunities.js.map +1 -0
- package/dist/tools/load-snapshot.d.ts +10 -0
- package/dist/tools/load-snapshot.d.ts.map +1 -1
- package/dist/tools/load-snapshot.js +152 -15
- package/dist/tools/load-snapshot.js.map +1 -1
- package/dist/tools/object-cost-breakdown.d.ts +12 -0
- package/dist/tools/object-cost-breakdown.d.ts.map +1 -0
- package/dist/tools/object-cost-breakdown.js +439 -0
- package/dist/tools/object-cost-breakdown.js.map +1 -0
- package/dist/tools/object-shape.d.ts.map +1 -1
- package/dist/tools/object-shape.js +95 -2
- package/dist/tools/object-shape.js.map +1 -1
- package/dist/tools/pinch-points.d.ts.map +1 -1
- package/dist/tools/pinch-points.js +9 -9
- package/dist/tools/pinch-points.js.map +1 -1
- package/dist/tools/property-distribution.d.ts +12 -0
- package/dist/tools/property-distribution.d.ts.map +1 -0
- package/dist/tools/property-distribution.js +168 -0
- package/dist/tools/property-distribution.js.map +1 -0
- package/dist/tools/quick-diagnosis.d.ts.map +1 -1
- package/dist/tools/quick-diagnosis.js +56 -19
- package/dist/tools/quick-diagnosis.js.map +1 -1
- package/dist/tools/retainer-summary.d.ts.map +1 -1
- package/dist/tools/retainer-summary.js +90 -5
- package/dist/tools/retainer-summary.js.map +1 -1
- package/dist/tools/retainer-trace.d.ts.map +1 -1
- package/dist/tools/retainer-trace.js +74 -22
- 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 +10 -3
- package/dist/tools/search-nodes.js.map +1 -1
- package/dist/tools/search-strings.d.ts +12 -0
- package/dist/tools/search-strings.d.ts.map +1 -0
- package/dist/tools/search-strings.js +182 -0
- package/dist/tools/search-strings.js.map +1 -0
- package/dist/tools/sequence-analysis.d.ts +12 -0
- package/dist/tools/sequence-analysis.d.ts.map +1 -0
- package/dist/tools/sequence-analysis.js +234 -0
- package/dist/tools/sequence-analysis.js.map +1 -0
- package/dist/tools/server-status.d.ts +12 -0
- package/dist/tools/server-status.d.ts.map +1 -0
- package/dist/tools/server-status.js +41 -0
- package/dist/tools/server-status.js.map +1 -0
- package/dist/tools/shape-histogram.d.ts.map +1 -1
- package/dist/tools/shape-histogram.js +61 -16
- package/dist/tools/shape-histogram.js.map +1 -1
- package/dist/tools/sliced-strings.d.ts.map +1 -1
- package/dist/tools/sliced-strings.js +16 -11
- package/dist/tools/sliced-strings.js.map +1 -1
- package/dist/tools/snapshot-summary.d.ts.map +1 -1
- package/dist/tools/snapshot-summary.js +55 -13
- package/dist/tools/snapshot-summary.js.map +1 -1
- package/dist/tools/snapshots.d.ts +12 -0
- package/dist/tools/snapshots.d.ts.map +1 -0
- package/dist/tools/snapshots.js +93 -0
- package/dist/tools/snapshots.js.map +1 -0
- package/dist/tools/stale-collections.d.ts.map +1 -1
- package/dist/tools/stale-collections.js +248 -7
- package/dist/tools/stale-collections.js.map +1 -1
- package/dist/tools/trace-dominators.d.ts.map +1 -1
- package/dist/tools/trace-dominators.js +28 -1
- package/dist/tools/trace-dominators.js.map +1 -1
- package/dist/tools/weakmap-entries.d.ts +12 -0
- package/dist/tools/weakmap-entries.d.ts.map +1 -0
- package/dist/tools/weakmap-entries.js +156 -0
- package/dist/tools/weakmap-entries.js.map +1 -0
- package/dist/utils.d.ts +81 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +303 -35
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { getSnapshot, getSnapshotMetadata } from '../heap-state.js';
|
|
12
|
-
import { isNodeWorthInspecting, formatBytes, formatNumber, markdownTable, truncateNodeName, errorResult, toolResult, } from '../utils.js';
|
|
12
|
+
import { isNodeWorthInspecting, formatBytes, formatNumber, markdownTable, truncateNodeName, errorResult, toolResult, suggestionsSuppressed, } from '../utils.js';
|
|
13
13
|
export function registerPinchPoints(server) {
|
|
14
14
|
server.tool('memlab_pinch_points', 'Find "pinch points" — small objects that retain disproportionately large subtrees in the dominator tree. These are the most impactful objects to free: a single cache, map, or closure whose removal would reclaim the most memory. Returns objects ranked by retained_size/self_size ratio, filtered to actionable user-code objects (excludes V8 internals).', {
|
|
15
15
|
limit: z
|
|
@@ -20,13 +20,13 @@ export function registerPinchPoints(server) {
|
|
|
20
20
|
min_retained_size: z
|
|
21
21
|
.number()
|
|
22
22
|
.optional()
|
|
23
|
-
.default(
|
|
24
|
-
.describe('Minimum retained size in bytes to consider (default
|
|
23
|
+
.default(524288)
|
|
24
|
+
.describe('Minimum retained size in bytes to consider (default 512 KB). Increase for large snapshots.'),
|
|
25
25
|
min_ratio: z
|
|
26
26
|
.number()
|
|
27
27
|
.optional()
|
|
28
|
-
.default(
|
|
29
|
-
.describe('Minimum retained_size/self_size ratio (default
|
|
28
|
+
.default(50)
|
|
29
|
+
.describe('Minimum retained_size/self_size ratio (default 50). Higher values find more extreme pinch points.'),
|
|
30
30
|
}, async ({ limit, min_retained_size, min_ratio }) => {
|
|
31
31
|
try {
|
|
32
32
|
const snapshot = getSnapshot();
|
|
@@ -109,11 +109,11 @@ export function registerPinchPoints(server) {
|
|
|
109
109
|
markdownTable(headers, rows, rightCols),
|
|
110
110
|
'',
|
|
111
111
|
'**Interpretation:** Each row is a small object retaining a large subtree. Freeing it (e.g., clearing a cache, removing an event listener) would reclaim the retained size.',
|
|
112
|
-
'',
|
|
113
|
-
'**Suggested next steps:**',
|
|
114
112
|
];
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
if (!suggestionsSuppressed()) {
|
|
114
|
+
const top = candidates[0];
|
|
115
|
+
lines.push('', '**Suggested next steps:**', `- Inspect top pinch point: \`memlab_get_node(${top.nodeId})\` → \`memlab_object_shape(${top.nodeId})\``, `- See what it retains: \`memlab_dominator_subtree(${top.nodeId})\``, `- Trace how it's kept alive: \`memlab_retainer_trace(${top.nodeId})\``);
|
|
116
|
+
}
|
|
117
117
|
return toolResult(lines.join('\n'));
|
|
118
118
|
}
|
|
119
119
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinch-points.js","sourceRoot":"","sources":["../../src/tools/pinch-points.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AAClE,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,UAAU,
|
|
1
|
+
{"version":3,"file":"pinch-points.js","sourceRoot":"","sources":["../../src/tools/pinch-points.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 registerPropertyDistribution(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=property-distribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-distribution.d.ts","sourceRoot":"","sources":["../../src/tools/property-distribution.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAmCvE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyJpE"}
|
|
@@ -0,0 +1,168 @@
|
|
|
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, getSnapshotMetadata } from '../heap-state.js';
|
|
12
|
+
import { formatBytes, formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
|
|
13
|
+
function readPropertyValue(target) {
|
|
14
|
+
if (target.isString) {
|
|
15
|
+
const s = target.toStringNode();
|
|
16
|
+
const v = s ? s.stringValue : target.name;
|
|
17
|
+
return v.length > 120 ? v.slice(0, 120) + '…' : v;
|
|
18
|
+
}
|
|
19
|
+
// Inline SMI: value is encoded as id >> 1 with self_size 0.
|
|
20
|
+
if (target.name === 'smi number' && target.self_size === 0) {
|
|
21
|
+
return String(target.id >> 1);
|
|
22
|
+
}
|
|
23
|
+
if (target.name === 'heap number')
|
|
24
|
+
return '(heap number)';
|
|
25
|
+
if (target.name === 'true' || target.name === 'false')
|
|
26
|
+
return target.name;
|
|
27
|
+
if (target.name === 'null' || target.name === 'undefined')
|
|
28
|
+
return target.name;
|
|
29
|
+
// Object/array values: summarize by class, not identity.
|
|
30
|
+
return `<${target.name} (${target.type})>`;
|
|
31
|
+
}
|
|
32
|
+
export function registerPropertyDistribution(server) {
|
|
33
|
+
server.tool('memlab_property_distribution', "For a given object class/shape and property, report the value cardinality plus the top-K most frequent values with their counts. The key tool for diagnosing cardinality explosions (e.g., an OpenTelemetry metric attribute, a cache key, or a per-record field whose unbounded distinct values blow up memory). Complements memlab_shape_histogram (which groups by property *names*) by showing the distribution of a single property's *values*.", {
|
|
34
|
+
property: z
|
|
35
|
+
.string()
|
|
36
|
+
.describe('The property name to analyze the value distribution of.'),
|
|
37
|
+
class_name: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.default('Object')
|
|
41
|
+
.describe('Constructor name of the objects to scan (default "Object"). Use the class shown by class_histogram/shape_histogram.'),
|
|
42
|
+
shape: z
|
|
43
|
+
.array(z.string())
|
|
44
|
+
.optional()
|
|
45
|
+
.describe('Optional exact property-name set to restrict to one shape (as reported by shape_histogram). Only objects whose property names match this set are counted.'),
|
|
46
|
+
top_k: z
|
|
47
|
+
.number()
|
|
48
|
+
.optional()
|
|
49
|
+
.default(15)
|
|
50
|
+
.describe('Number of most-frequent values to show (default 15).'),
|
|
51
|
+
min_count: z
|
|
52
|
+
.number()
|
|
53
|
+
.optional()
|
|
54
|
+
.default(1)
|
|
55
|
+
.describe('Only show values occurring at least this many times.'),
|
|
56
|
+
}, async ({ property, class_name, shape, top_k, min_count }) => {
|
|
57
|
+
try {
|
|
58
|
+
const snapshot = getSnapshot();
|
|
59
|
+
const meta = getSnapshotMetadata();
|
|
60
|
+
const totalSize = meta?.totalSize ?? 0;
|
|
61
|
+
const shapeSet = shape ? new Set(shape) : null;
|
|
62
|
+
const values = new Map();
|
|
63
|
+
let matched = 0;
|
|
64
|
+
let withProp = 0;
|
|
65
|
+
let totalValueBytes = 0;
|
|
66
|
+
snapshot.nodes.forEach(node => {
|
|
67
|
+
if (node.id <= 3 || node.type !== 'object')
|
|
68
|
+
return;
|
|
69
|
+
if (node.name !== class_name)
|
|
70
|
+
return;
|
|
71
|
+
// Collect property names + locate the target property in one pass.
|
|
72
|
+
let target = null;
|
|
73
|
+
const propNames = [];
|
|
74
|
+
for (const edge of node.references) {
|
|
75
|
+
if (edge.type !== 'property')
|
|
76
|
+
continue;
|
|
77
|
+
const pName = String(edge.name_or_index);
|
|
78
|
+
propNames.push(pName);
|
|
79
|
+
if (pName === property)
|
|
80
|
+
target = edge.toNode;
|
|
81
|
+
}
|
|
82
|
+
if (shapeSet) {
|
|
83
|
+
if (propNames.length !== shapeSet.size)
|
|
84
|
+
return;
|
|
85
|
+
for (const p of propNames)
|
|
86
|
+
if (!shapeSet.has(p))
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
matched++;
|
|
90
|
+
if (!target)
|
|
91
|
+
return;
|
|
92
|
+
withProp++;
|
|
93
|
+
const key = readPropertyValue(target);
|
|
94
|
+
const bytes = target.isString ? target.self_size : 0;
|
|
95
|
+
totalValueBytes += bytes;
|
|
96
|
+
const existing = values.get(key);
|
|
97
|
+
if (existing) {
|
|
98
|
+
existing.count++;
|
|
99
|
+
existing.approxBytes += bytes;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
values.set(key, {
|
|
103
|
+
count: 1,
|
|
104
|
+
exampleNodeId: node.id,
|
|
105
|
+
approxBytes: bytes,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
if (matched === 0) {
|
|
110
|
+
return toolResult(`No \`${class_name}\` objects${shapeSet ? ' matching that shape' : ''} found. Check the class name with memlab_class_histogram or shape with memlab_shape_histogram.`);
|
|
111
|
+
}
|
|
112
|
+
const cardinality = values.size;
|
|
113
|
+
const sorted = [...values.entries()]
|
|
114
|
+
.filter(([, v]) => v.count >= min_count)
|
|
115
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
116
|
+
.slice(0, top_k);
|
|
117
|
+
const lines = [
|
|
118
|
+
`## Value distribution of \`${property}\` on \`${class_name}\`${shapeSet ? ' (shape-filtered)' : ''}`,
|
|
119
|
+
'',
|
|
120
|
+
`Objects scanned: ${formatNumber(matched)} | with property: ${formatNumber(withProp)} | distinct values: **${formatNumber(cardinality)}**` +
|
|
121
|
+
(totalValueBytes > 0
|
|
122
|
+
? ` | string value bytes: ${formatBytes(totalValueBytes)}` +
|
|
123
|
+
(totalSize > 0
|
|
124
|
+
? ` (${Math.min(100, (totalValueBytes / totalSize) * 100).toFixed(1)}% of heap)`
|
|
125
|
+
: '')
|
|
126
|
+
: ''),
|
|
127
|
+
'',
|
|
128
|
+
];
|
|
129
|
+
// Cardinality interpretation.
|
|
130
|
+
const ratio = withProp > 0 ? cardinality / withProp : 0;
|
|
131
|
+
if (cardinality === 1) {
|
|
132
|
+
lines.push(`_Single constant value across all instances — strong candidate for interning or dropping the field._`);
|
|
133
|
+
}
|
|
134
|
+
else if (ratio > 0.9 && withProp >= 100) {
|
|
135
|
+
lines.push(`_Nearly all values are unique (${(ratio * 100).toFixed(0)}% distinct) — a high-cardinality field. If this feeds a metric dimension or cache key, that is likely the cardinality-explosion root cause._`);
|
|
136
|
+
}
|
|
137
|
+
else if (cardinality <= 20) {
|
|
138
|
+
lines.push(`_Low cardinality (${cardinality} values) — can usually be bucketed/filtered at the source or interned._`);
|
|
139
|
+
}
|
|
140
|
+
lines.push('');
|
|
141
|
+
const headers = [
|
|
142
|
+
'Value',
|
|
143
|
+
'Count',
|
|
144
|
+
'% of instances',
|
|
145
|
+
'Str bytes',
|
|
146
|
+
'Example',
|
|
147
|
+
];
|
|
148
|
+
const rightCols = new Set([1, 2, 3]);
|
|
149
|
+
const rows = sorted.map(([val, v]) => [
|
|
150
|
+
val.length > 60 ? val.slice(0, 57) + '…' : val,
|
|
151
|
+
formatNumber(v.count),
|
|
152
|
+
withProp > 0 ? ((v.count / withProp) * 100).toFixed(1) + '%' : '-',
|
|
153
|
+
v.approxBytes > 0 ? formatBytes(v.approxBytes) : '-',
|
|
154
|
+
`@${v.exampleNodeId}`,
|
|
155
|
+
]);
|
|
156
|
+
lines.push(markdownTable(headers, rows, rightCols));
|
|
157
|
+
if (cardinality > sorted.length) {
|
|
158
|
+
lines.push('');
|
|
159
|
+
lines.push(`… and ${formatNumber(cardinality - sorted.length)} more distinct value(s). Increase top_k to see more.`);
|
|
160
|
+
}
|
|
161
|
+
return toolResult(lines.join('\n'));
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
return errorResult(err);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=property-distribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-distribution.js","sourceRoot":"","sources":["../../src/tools/property-distribution.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quick-diagnosis.d.ts","sourceRoot":"","sources":["../../src/tools/quick-diagnosis.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAoDvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"quick-diagnosis.d.ts","sourceRoot":"","sources":["../../src/tools/quick-diagnosis.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAoDvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2S9D"}
|
|
@@ -41,7 +41,8 @@ function getContentPreview(node) {
|
|
|
41
41
|
return '';
|
|
42
42
|
}
|
|
43
43
|
export function registerQuickDiagnosis(server) {
|
|
44
|
-
server.tool('memlab_quick_diagnosis', 'Combined diagnosis tool that returns snapshot summary, top objects by retained size, class histogram, and duplicated strings in a single call. Saves 3-4 round trips and reduces token overhead from repeated headers. Use this as the first analysis tool after memlab_load_snapshot for an immediate comprehensive overview.'
|
|
44
|
+
server.tool('memlab_quick_diagnosis', 'Combined diagnosis tool that returns snapshot summary, top objects by retained size, class histogram, and duplicated strings in a single call. Saves 3-4 round trips and reduces token overhead from repeated headers. Use this as the first analysis tool after memlab_load_snapshot for an immediate comprehensive overview. ' +
|
|
45
|
+
'By DEFAULT every section runs in a single O(N) pass (the class histogram reports retained size as a lower/upper-bound range rather than the exact dominator-deduped value), so it is safe on large heaps. Pass `exact_retained_size:true` ONLY when the user explicitly wants exact per-class retained sizes — that adds a per-class dominator walk that can stall or OOM the server on snapshots with millions of nodes.', {
|
|
45
46
|
top_objects: z
|
|
46
47
|
.number()
|
|
47
48
|
.optional()
|
|
@@ -57,7 +58,12 @@ export function registerQuickDiagnosis(server) {
|
|
|
57
58
|
.optional()
|
|
58
59
|
.default(10)
|
|
59
60
|
.describe('Number of top duplicated strings (default 10)'),
|
|
60
|
-
|
|
61
|
+
exact_retained_size: z
|
|
62
|
+
.boolean()
|
|
63
|
+
.optional()
|
|
64
|
+
.default(false)
|
|
65
|
+
.describe('Compute EXACT dominator-deduped retained size for the class histogram via aggregateDominatorMetrics. DEFAULT false: the class histogram shows a retained-size range (lower = self size, upper = Σ raw retained) computed in the O(N) pass. Set true ONLY on explicit user request — the exact walk can be very slow or time out on huge heaps.'),
|
|
66
|
+
}, async ({ top_objects, top_classes, top_strings, exact_retained_size }) => {
|
|
61
67
|
try {
|
|
62
68
|
const snapshot = getSnapshot();
|
|
63
69
|
const meta = getSnapshotMetadata();
|
|
@@ -125,47 +131,61 @@ export function registerQuickDiagnosis(server) {
|
|
|
125
131
|
if (entry) {
|
|
126
132
|
entry.count++;
|
|
127
133
|
entry.total_self_size += node.self_size;
|
|
128
|
-
entry.
|
|
134
|
+
entry.raw_retained += node.retainedSize;
|
|
135
|
+
if (entry.node_ids)
|
|
136
|
+
entry.node_ids.add(node.id);
|
|
129
137
|
}
|
|
130
138
|
else {
|
|
131
139
|
classMap.set(key, {
|
|
132
140
|
count: 1,
|
|
133
141
|
total_self_size: node.self_size,
|
|
134
|
-
|
|
142
|
+
raw_retained: node.retainedSize,
|
|
143
|
+
// Per-node ids are only needed for the opt-in exact dominator walk.
|
|
144
|
+
node_ids: exact_retained_size ? new NumericSet([node.id]) : null,
|
|
135
145
|
type: node.type,
|
|
136
146
|
});
|
|
137
147
|
}
|
|
138
148
|
});
|
|
139
149
|
const classEntries = [...classMap.entries()].filter(([, v]) => v.count >= 1);
|
|
150
|
+
// By DEFAULT skip the exact dominator walk (the part that stalls the
|
|
151
|
+
// server on huge heaps) and rank by the upper-bound raw retained sum;
|
|
152
|
+
// only compute exact dominator-deduped retained when explicitly asked.
|
|
140
153
|
const withRetained = classEntries.map(([key, v]) => {
|
|
141
|
-
|
|
142
|
-
|
|
154
|
+
let exact = null;
|
|
155
|
+
if (exact_retained_size && v.node_ids) {
|
|
156
|
+
exact = utils.aggregateDominatorMetrics(v.node_ids, snapshot, () => true, (node) => node.retainedSize);
|
|
157
|
+
}
|
|
158
|
+
const rank = exact ?? v.raw_retained;
|
|
159
|
+
return { key, ...v, exact, rank };
|
|
143
160
|
});
|
|
144
|
-
// Use total heap size as denominator so cumulative % reflects each
|
|
145
|
-
// class's share of the entire heap, not just the displayed classes.
|
|
146
161
|
const totalClassRetained = meta?.totalSize ?? 0;
|
|
147
162
|
const classSorted = withRetained
|
|
148
|
-
.sort((a, b) => b.
|
|
163
|
+
.sort((a, b) => b.rank - a.rank)
|
|
149
164
|
.slice(0, top_classes);
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
const classHeaders = exact_retained_size
|
|
166
|
+
? ['Class', 'Type', 'Count', 'Retained', '% Heap']
|
|
167
|
+
: ['Class', 'Type', 'Count', 'Retained ≤ (upper)', '% Heap ≤'];
|
|
152
168
|
const classRightCols = new Set([2, 3, 4]);
|
|
153
169
|
const classRows = classSorted.map(v => {
|
|
154
170
|
const rawName = v.key.split('::').slice(1).join('::');
|
|
155
171
|
const name = truncateNodeName(rawName, v.type, Math.round(v.total_self_size / v.count), 80);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
? ((cumRetained / totalClassRetained) * 100).toFixed(1) + '%'
|
|
172
|
+
const pct = totalClassRetained > 0
|
|
173
|
+
? ((v.rank / totalClassRetained) * 100).toFixed(1) + '%'
|
|
159
174
|
: '-';
|
|
160
175
|
return [
|
|
161
176
|
name,
|
|
162
177
|
v.type,
|
|
163
178
|
formatNumber(v.count),
|
|
164
|
-
|
|
165
|
-
|
|
179
|
+
exact_retained_size
|
|
180
|
+
? formatBytes(v.exact ?? 0)
|
|
181
|
+
: `≤ ${formatBytes(v.raw_retained)}`,
|
|
182
|
+
exact_retained_size ? pct : `≤ ${pct}`,
|
|
166
183
|
];
|
|
167
184
|
});
|
|
168
185
|
lines.push(`## Class Histogram (top ${classRows.length})`, '', markdownTable(classHeaders, classRows, classRightCols), '');
|
|
186
|
+
if (!exact_retained_size) {
|
|
187
|
+
lines.push("_Class `Retained` is an **upper bound** (Σ each instance's retained size, which double-counts shared subtrees); the lower bound is the class self size. The exact dominator-deduped value needs a per-class dominator walk (slow / can time out on large heaps) — pass `exact_retained_size:true` for it._", '');
|
|
188
|
+
}
|
|
169
189
|
// --- Section 4: Duplicated Strings ---
|
|
170
190
|
const stringMap = new Map();
|
|
171
191
|
snapshot.nodes.forEach(node => {
|
|
@@ -191,17 +211,34 @@ export function registerQuickDiagnosis(server) {
|
|
|
191
211
|
.sort((a, b) => b[1].total_size - a[1].total_size)
|
|
192
212
|
.slice(0, top_strings);
|
|
193
213
|
if (duplicated.length > 0) {
|
|
194
|
-
const strHeaders = ['Value', 'Copies', 'Total Size'];
|
|
195
|
-
const strRightCols = new Set([1, 2]);
|
|
214
|
+
const strHeaders = ['Value', 'Copies', 'Total Size', 'Savings'];
|
|
215
|
+
const strRightCols = new Set([1, 2, 3]);
|
|
196
216
|
const strRows = duplicated.map(([value, stats]) => {
|
|
197
217
|
const display = value.length > 50 ? value.slice(0, 50) + '…' : value;
|
|
218
|
+
const perCopy = stats.count > 0 ? stats.total_size / stats.count : 0;
|
|
219
|
+
const savings = (stats.count - 1) * perCopy;
|
|
198
220
|
return [
|
|
199
221
|
sanitizeForTable(display),
|
|
200
222
|
formatNumber(stats.count),
|
|
201
223
|
formatBytes(stats.total_size),
|
|
224
|
+
formatBytes(savings),
|
|
202
225
|
];
|
|
203
226
|
});
|
|
204
|
-
|
|
227
|
+
const totalDupSavings = duplicated.reduce((sum, [, stats]) => {
|
|
228
|
+
const perCopy = stats.count > 0 ? stats.total_size / stats.count : 0;
|
|
229
|
+
return sum + (stats.count - 1) * perCopy;
|
|
230
|
+
}, 0);
|
|
231
|
+
lines.push(`## Duplicated Strings (top ${strRows.length})`, '', markdownTable(strHeaders, strRows, strRightCols), '', `**Total interning savings: ${formatBytes(totalDupSavings)}** (if each string stored once)`, '');
|
|
232
|
+
}
|
|
233
|
+
// --- Section 5: String-to-Object Ratio Flag (Feedback #11) ---
|
|
234
|
+
const stringCount = typeStats.get('string')?.count ?? 0;
|
|
235
|
+
const objectCount = typeStats.get('object')?.count ?? 0;
|
|
236
|
+
const heavyDupCount = duplicated.filter(([, stats]) => stats.count >= 100_000).length;
|
|
237
|
+
if (objectCount > 0 &&
|
|
238
|
+
stringCount / objectCount > 2 &&
|
|
239
|
+
heavyDupCount > 0) {
|
|
240
|
+
const ratio = (stringCount / objectCount).toFixed(1);
|
|
241
|
+
lines.push('## ⚠️ High String Duplication Ratio', '', `**${formatNumber(stringCount)} strings / ${formatNumber(objectCount)} objects = ${ratio}:1 ratio** with ${heavyDupCount} string(s) having >100K copies.`, '', 'This pattern strongly indicates JSON.parse output or API response data where column values are not interned. String interning at the parse boundary could save significant memory.', '', '**Next step:** `memlab_intern_opportunities` to see savings grouped by property × parent shape.', '');
|
|
205
242
|
}
|
|
206
243
|
return toolResult(lines.join('\n'));
|
|
207
244
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quick-diagnosis.js","sourceRoot":"","sources":["../../src/tools/quick-diagnosis.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"quick-diagnosis.js","sourceRoot":"","sources":["../../src/tools/quick-diagnosis.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retainer-summary.d.ts","sourceRoot":"","sources":["../../src/tools/retainer-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"retainer-summary.d.ts","sourceRoot":"","sources":["../../src/tools/retainer-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA2IvE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuX/D"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { getSnapshot } from '../heap-state.js';
|
|
12
|
-
import { filterLargestObjects, formatBytes, errorResult, toolResult, } from '../utils.js';
|
|
12
|
+
import { filterLargestObjects, formatBytes, truncateDomToTag, errorResult, toolResult, } from '../utils.js';
|
|
13
13
|
const FRAMEWORK_PATTERNS = new Set([
|
|
14
14
|
'system / Context',
|
|
15
15
|
'system / PromiseReaction',
|
|
@@ -79,6 +79,12 @@ function traceToKey(steps, frameworkFilter) {
|
|
|
79
79
|
.join(' ');
|
|
80
80
|
}
|
|
81
81
|
function shortenPath(name) {
|
|
82
|
+
const isDomLike = name.includes('class="') ||
|
|
83
|
+
name.includes('aria-') ||
|
|
84
|
+
name.startsWith('<') ||
|
|
85
|
+
name.startsWith('Detached <');
|
|
86
|
+
if (isDomLike)
|
|
87
|
+
return truncateDomToTag(name);
|
|
82
88
|
if (name.length <= 40)
|
|
83
89
|
return name;
|
|
84
90
|
const parts = name.split('/');
|
|
@@ -127,6 +133,13 @@ export function registerRetainerSummary(server) {
|
|
|
127
133
|
.string()
|
|
128
134
|
.optional()
|
|
129
135
|
.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.'),
|
|
136
|
+
shape: z
|
|
137
|
+
.array(z.string())
|
|
138
|
+
.optional()
|
|
139
|
+
.describe('Find objects by property shape — objects that have ALL of these property names. ' +
|
|
140
|
+
'Use instead of class_name when constructor is "Object" and you know the property ' +
|
|
141
|
+
'structure (e.g., ["callback", "context"]). Matches the {prop1, prop2} naming ' +
|
|
142
|
+
'from shape_histogram output.'),
|
|
130
143
|
node_ids: z
|
|
131
144
|
.array(z.number())
|
|
132
145
|
.optional()
|
|
@@ -150,7 +163,14 @@ export function registerRetainerSummary(server) {
|
|
|
150
163
|
.optional()
|
|
151
164
|
.default(false)
|
|
152
165
|
.describe('Exclude known V8/Node.js framework internals (system / Context, PromiseReaction, module cache patterns) from retainer paths. Helps surface application-level retention.'),
|
|
153
|
-
|
|
166
|
+
include_properties: z
|
|
167
|
+
.boolean()
|
|
168
|
+
.optional()
|
|
169
|
+
.default(false)
|
|
170
|
+
.describe('For each sampled node, also show its direct property edges (name -> target type/name). ' +
|
|
171
|
+
'Combines "where is it retained?" with "what does it contain?" in one call. ' +
|
|
172
|
+
'Saves a follow-up memlab_object_shape call per node.'),
|
|
173
|
+
}, async ({ class_name, name_prefix, shape, node_ids, sample, max_depth, compact, framework_filter, include_properties, }) => {
|
|
154
174
|
try {
|
|
155
175
|
const snapshot = getSnapshot();
|
|
156
176
|
let nodes;
|
|
@@ -164,6 +184,23 @@ export function registerRetainerSummary(server) {
|
|
|
164
184
|
}
|
|
165
185
|
label = `${nodes.length} specified node(s)`;
|
|
166
186
|
}
|
|
187
|
+
else if (shape && shape.length > 0) {
|
|
188
|
+
const requiredProps = new Set(shape);
|
|
189
|
+
nodes = filterLargestObjects(snapshot, node => {
|
|
190
|
+
if (node.type !== 'object' || node.id <= 3)
|
|
191
|
+
return false;
|
|
192
|
+
const foundProps = new Set();
|
|
193
|
+
for (const edge of node.references) {
|
|
194
|
+
if (edge.type === 'property') {
|
|
195
|
+
const name = String(edge.name_or_index);
|
|
196
|
+
if (requiredProps.has(name))
|
|
197
|
+
foundProps.add(name);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return foundProps.size === requiredProps.size;
|
|
201
|
+
}, sample);
|
|
202
|
+
label = `shape {${shape.join(', ')}}`;
|
|
203
|
+
}
|
|
167
204
|
else if (name_prefix) {
|
|
168
205
|
nodes = filterLargestObjects(snapshot, node => node.name.startsWith(name_prefix), sample);
|
|
169
206
|
label = `prefix "${name_prefix}"`;
|
|
@@ -179,10 +216,14 @@ export function registerRetainerSummary(server) {
|
|
|
179
216
|
label = `"${class_name}"`;
|
|
180
217
|
}
|
|
181
218
|
else {
|
|
182
|
-
return errorResult(new Error('Either class_name, name_prefix, or node_ids must be provided.'));
|
|
219
|
+
return errorResult(new Error('Either class_name, name_prefix, shape, or node_ids must be provided.'));
|
|
183
220
|
}
|
|
184
221
|
if (nodes.length === 0) {
|
|
185
|
-
|
|
222
|
+
const suggestions = [`No objects found for ${label}.`, ''];
|
|
223
|
+
if (class_name) {
|
|
224
|
+
suggestions.push(`**Possible reasons:**`, `- The class name may not match exactly — V8 uses constructor names, not class declarations`, `- For DOM nodes, try \`name_prefix: "Detached"\` instead of class_name`, `- For shape-based queries, use \`memlab_find_by_shape\` with property names instead`, '', `**Try instead:**`, `- \`memlab_search_nodes\` with a regex pattern to find partial matches`, `- \`memlab_class_histogram\` to see all class names in the snapshot`, `- \`memlab_find_by_property\` if you know a property name on the target objects`);
|
|
225
|
+
}
|
|
226
|
+
return toolResult(suggestions.join('\n'));
|
|
186
227
|
}
|
|
187
228
|
const patterns = new Map();
|
|
188
229
|
let noTrace = 0;
|
|
@@ -292,10 +333,54 @@ export function registerRetainerSummary(server) {
|
|
|
292
333
|
: formatFn(displaySteps));
|
|
293
334
|
lines.push('');
|
|
294
335
|
lines.push(`Example nodes: ${p.example_ids.map(id => `@${id}`).join(', ')}`);
|
|
336
|
+
if (include_properties) {
|
|
337
|
+
for (const exId of p.example_ids.slice(0, 2)) {
|
|
338
|
+
const exNode = snapshot.getNodeById(exId);
|
|
339
|
+
if (!exNode)
|
|
340
|
+
continue;
|
|
341
|
+
const props = [];
|
|
342
|
+
for (const edge of exNode.references) {
|
|
343
|
+
if (edge.type === 'property' ||
|
|
344
|
+
edge.type === 'element' ||
|
|
345
|
+
edge.type === 'context') {
|
|
346
|
+
const target = edge.toNode;
|
|
347
|
+
if (target.id <= 3)
|
|
348
|
+
continue;
|
|
349
|
+
let valPreview;
|
|
350
|
+
if (target.isString) {
|
|
351
|
+
const strNode = target.toStringNode();
|
|
352
|
+
const sv = strNode?.stringValue ?? target.name;
|
|
353
|
+
valPreview = `"${sv.length > 30 ? sv.slice(0, 27) + '...' : sv}"`;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
valPreview = `${target.name} (${target.type})`;
|
|
357
|
+
}
|
|
358
|
+
props.push(`${String(edge.name_or_index)}: ${valPreview}`);
|
|
359
|
+
if (props.length >= 8)
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (props.length > 0) {
|
|
364
|
+
lines.push(` @${exId} properties: {${props.join(', ')}}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
295
368
|
lines.push('');
|
|
296
369
|
}
|
|
297
370
|
if (noTrace > 0) {
|
|
298
|
-
|
|
371
|
+
const noTraceNodes = nodes.filter(n => !n.hasPathEdge);
|
|
372
|
+
const withReferrers = noTraceNodes.filter(n => n.numOfReferrers > 0).length;
|
|
373
|
+
const noReferrers = noTrace - withReferrers;
|
|
374
|
+
const parts = [
|
|
375
|
+
`${noTrace} instance(s) had no retainer path:`,
|
|
376
|
+
];
|
|
377
|
+
if (noReferrers > 0) {
|
|
378
|
+
parts.push(`${noReferrers} with no referrers (GC-eligible, safe to ignore)`);
|
|
379
|
+
}
|
|
380
|
+
if (withReferrers > 0) {
|
|
381
|
+
parts.push(`${withReferrers} with referrers but no GC root path (possibly weak-only retention — use \`memlab_get_referrers\` to inspect)`);
|
|
382
|
+
}
|
|
383
|
+
lines.push(`(${parts.join('; ')})`);
|
|
299
384
|
}
|
|
300
385
|
return toolResult(lines.join('\n'));
|
|
301
386
|
}
|