@memlab/mcp-server 2.52.0 → 2.86.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 +22 -2
- package/dist/anonymized-snapshot.d.ts +75 -0
- package/dist/anonymized-snapshot.d.ts.map +1 -0
- package/dist/anonymized-snapshot.js +101 -0
- package/dist/anonymized-snapshot.js.map +1 -0
- package/dist/eval-hints.d.ts +41 -0
- package/dist/eval-hints.d.ts.map +1 -0
- package/dist/eval-hints.js +115 -0
- package/dist/eval-hints.js.map +1 -0
- package/dist/heap-budget.d.ts +32 -0
- package/dist/heap-budget.d.ts.map +1 -0
- package/dist/heap-budget.js +90 -0
- package/dist/heap-budget.js.map +1 -0
- package/dist/heap-shapes.d.ts +148 -0
- package/dist/heap-shapes.d.ts.map +1 -0
- package/dist/heap-shapes.js +193 -0
- package/dist/heap-shapes.js.map +1 -0
- package/dist/heap-state.d.ts +20 -0
- package/dist/heap-state.d.ts.map +1 -1
- package/dist/heap-state.js +8 -1
- package/dist/heap-state.js.map +1 -1
- package/dist/index.js +64 -1
- package/dist/index.js.map +1 -1
- package/dist/react-shapes.d.ts +42 -0
- package/dist/react-shapes.d.ts.map +1 -0
- package/dist/react-shapes.js +149 -0
- package/dist/react-shapes.js.map +1 -0
- package/dist/server-version.d.ts +19 -0
- package/dist/server-version.d.ts.map +1 -0
- package/dist/server-version.js +19 -0
- package/dist/server-version.js.map +1 -0
- package/dist/snapshot-borrow.d.ts +67 -0
- package/dist/snapshot-borrow.d.ts.map +1 -0
- package/dist/snapshot-borrow.js +113 -0
- package/dist/snapshot-borrow.js.map +1 -0
- package/dist/string-index.d.ts.map +1 -1
- package/dist/string-index.js +8 -0
- package/dist/string-index.js.map +1 -1
- package/dist/tools/analyze-run.d.ts.map +1 -1
- package/dist/tools/analyze-run.js +79 -18
- package/dist/tools/analyze-run.js.map +1 -1
- package/dist/tools/anonymize-snapshot.d.ts +12 -0
- package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
- package/dist/tools/anonymize-snapshot.js +159 -0
- package/dist/tools/anonymize-snapshot.js.map +1 -0
- package/dist/tools/app-config.d.ts +12 -0
- package/dist/tools/app-config.d.ts.map +1 -0
- package/dist/tools/app-config.js +217 -0
- package/dist/tools/app-config.js.map +1 -0
- package/dist/tools/app-heap.d.ts +18 -0
- package/dist/tools/app-heap.d.ts.map +1 -1
- package/dist/tools/app-heap.js +12 -46
- package/dist/tools/app-heap.js.map +1 -1
- package/dist/tools/artifact-budget.d.ts +12 -0
- package/dist/tools/artifact-budget.d.ts.map +1 -0
- package/dist/tools/artifact-budget.js +219 -0
- package/dist/tools/artifact-budget.js.map +1 -0
- package/dist/tools/async-census.d.ts +12 -0
- package/dist/tools/async-census.d.ts.map +1 -0
- package/dist/tools/async-census.js +243 -0
- package/dist/tools/async-census.js.map +1 -0
- package/dist/tools/auto-investigate.d.ts.map +1 -1
- package/dist/tools/auto-investigate.js +54 -5
- package/dist/tools/auto-investigate.js.map +1 -1
- package/dist/tools/batch.d.ts.map +1 -1
- package/dist/tools/batch.js +33 -5
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/cache-analysis.d.ts +15 -0
- package/dist/tools/cache-analysis.d.ts.map +1 -1
- package/dist/tools/cache-analysis.js +85 -10
- package/dist/tools/cache-analysis.js.map +1 -1
- package/dist/tools/census-diff.d.ts +55 -0
- package/dist/tools/census-diff.d.ts.map +1 -0
- package/dist/tools/census-diff.js +228 -0
- package/dist/tools/census-diff.js.map +1 -0
- package/dist/tools/chain-walk.d.ts +12 -0
- package/dist/tools/chain-walk.d.ts.map +1 -0
- package/dist/tools/chain-walk.js +184 -0
- package/dist/tools/chain-walk.js.map +1 -0
- package/dist/tools/collection-diff.d.ts +44 -0
- package/dist/tools/collection-diff.d.ts.map +1 -0
- package/dist/tools/collection-diff.js +343 -0
- package/dist/tools/collection-diff.js.map +1 -0
- package/dist/tools/collection-trend.d.ts.map +1 -1
- package/dist/tools/collection-trend.js +2 -2
- package/dist/tools/collection-trend.js.map +1 -1
- package/dist/tools/detached-dom.d.ts +3 -0
- package/dist/tools/detached-dom.d.ts.map +1 -1
- package/dist/tools/detached-dom.js +78 -3
- package/dist/tools/detached-dom.js.map +1 -1
- package/dist/tools/dev-artifacts.d.ts.map +1 -1
- package/dist/tools/dev-artifacts.js +221 -3
- package/dist/tools/dev-artifacts.js.map +1 -1
- package/dist/tools/diff-snapshots.d.ts.map +1 -1
- package/dist/tools/diff-snapshots.js +18 -2
- package/dist/tools/diff-snapshots.js.map +1 -1
- package/dist/tools/dom-audit.d.ts +37 -0
- package/dist/tools/dom-audit.d.ts.map +1 -0
- package/dist/tools/dom-audit.js +247 -0
- package/dist/tools/dom-audit.js.map +1 -0
- package/dist/tools/duplicated-strings.d.ts.map +1 -1
- package/dist/tools/duplicated-strings.js +3 -2
- package/dist/tools/duplicated-strings.js.map +1 -1
- package/dist/tools/eval-across.d.ts +12 -0
- package/dist/tools/eval-across.d.ts.map +1 -0
- package/dist/tools/eval-across.js +135 -0
- package/dist/tools/eval-across.js.map +1 -0
- package/dist/tools/eval.d.ts +78 -0
- package/dist/tools/eval.d.ts.map +1 -1
- package/dist/tools/eval.js +2270 -701
- 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 +42 -17
- package/dist/tools/event-listener-leaks.js.map +1 -1
- package/dist/tools/event-registry.d.ts.map +1 -1
- package/dist/tools/event-registry.js +42 -8
- package/dist/tools/event-registry.js.map +1 -1
- package/dist/tools/explain-delta.d.ts.map +1 -1
- package/dist/tools/explain-delta.js +61 -10
- package/dist/tools/explain-delta.js.map +1 -1
- package/dist/tools/finding-index.d.ts +181 -0
- package/dist/tools/finding-index.d.ts.map +1 -1
- package/dist/tools/finding-index.js +343 -24
- package/dist/tools/finding-index.js.map +1 -1
- package/dist/tools/get-value.d.ts +16 -0
- package/dist/tools/get-value.d.ts.map +1 -1
- package/dist/tools/get-value.js +96 -2
- package/dist/tools/get-value.js.map +1 -1
- package/dist/tools/hypothesis.d.ts.map +1 -1
- package/dist/tools/hypothesis.js +117 -58
- package/dist/tools/hypothesis.js.map +1 -1
- package/dist/tools/id-space-audit.d.ts +12 -0
- package/dist/tools/id-space-audit.d.ts.map +1 -0
- package/dist/tools/id-space-audit.js +262 -0
- package/dist/tools/id-space-audit.js.map +1 -0
- package/dist/tools/identify.d.ts +12 -0
- package/dist/tools/identify.d.ts.map +1 -0
- package/dist/tools/identify.js +205 -0
- package/dist/tools/identify.js.map +1 -0
- package/dist/tools/identity-diff.d.ts +12 -0
- package/dist/tools/identity-diff.d.ts.map +1 -0
- package/dist/tools/identity-diff.js +188 -0
- package/dist/tools/identity-diff.js.map +1 -0
- package/dist/tools/intern-opportunities.d.ts.map +1 -1
- package/dist/tools/intern-opportunities.js +4 -3
- package/dist/tools/intern-opportunities.js.map +1 -1
- package/dist/tools/ladder-probe.d.ts +65 -0
- package/dist/tools/ladder-probe.d.ts.map +1 -0
- package/dist/tools/ladder-probe.js +445 -0
- package/dist/tools/ladder-probe.js.map +1 -0
- package/dist/tools/ladder.d.ts.map +1 -1
- package/dist/tools/ladder.js +5 -5
- package/dist/tools/ladder.js.map +1 -1
- package/dist/tools/leak-report.d.ts +23 -0
- package/dist/tools/leak-report.d.ts.map +1 -1
- package/dist/tools/leak-report.js +153 -11
- package/dist/tools/leak-report.js.map +1 -1
- package/dist/tools/load-snapshot.d.ts +11 -0
- package/dist/tools/load-snapshot.d.ts.map +1 -1
- package/dist/tools/load-snapshot.js +83 -10
- package/dist/tools/load-snapshot.js.map +1 -1
- package/dist/tools/metric.d.ts +13 -0
- package/dist/tools/metric.d.ts.map +1 -0
- package/dist/tools/metric.js +185 -0
- package/dist/tools/metric.js.map +1 -0
- package/dist/tools/module-attribution.d.ts +36 -0
- package/dist/tools/module-attribution.d.ts.map +1 -0
- package/dist/tools/module-attribution.js +235 -0
- package/dist/tools/module-attribution.js.map +1 -0
- package/dist/tools/next-measurement.d.ts +26 -0
- package/dist/tools/next-measurement.d.ts.map +1 -0
- package/dist/tools/next-measurement.js +149 -0
- package/dist/tools/next-measurement.js.map +1 -0
- package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
- package/dist/tools/object-cost-breakdown.js +64 -0
- package/dist/tools/object-cost-breakdown.js.map +1 -1
- package/dist/tools/population-vs-owners.d.ts +12 -0
- package/dist/tools/population-vs-owners.d.ts.map +1 -0
- package/dist/tools/population-vs-owners.js +183 -0
- package/dist/tools/population-vs-owners.js.map +1 -0
- package/dist/tools/property-names.d.ts +29 -0
- package/dist/tools/property-names.d.ts.map +1 -0
- package/dist/tools/property-names.js +131 -0
- package/dist/tools/property-names.js.map +1 -0
- package/dist/tools/quick-diagnosis.d.ts.map +1 -1
- package/dist/tools/quick-diagnosis.js +7 -1
- package/dist/tools/quick-diagnosis.js.map +1 -1
- package/dist/tools/react-owners.d.ts +12 -0
- package/dist/tools/react-owners.d.ts.map +1 -0
- package/dist/tools/react-owners.js +167 -0
- package/dist/tools/react-owners.js.map +1 -0
- package/dist/tools/react-update-queues.d.ts +12 -0
- package/dist/tools/react-update-queues.d.ts.map +1 -0
- package/dist/tools/react-update-queues.js +173 -0
- package/dist/tools/react-update-queues.js.map +1 -0
- package/dist/tools/replicate.d.ts +49 -0
- package/dist/tools/replicate.d.ts.map +1 -0
- package/dist/tools/replicate.js +241 -0
- package/dist/tools/replicate.js.map +1 -0
- package/dist/tools/retainer-diff.d.ts +12 -0
- package/dist/tools/retainer-diff.d.ts.map +1 -0
- package/dist/tools/retainer-diff.js +168 -0
- package/dist/tools/retainer-diff.js.map +1 -0
- package/dist/tools/retainer-summary.d.ts +17 -0
- package/dist/tools/retainer-summary.d.ts.map +1 -1
- package/dist/tools/retainer-summary.js +85 -22
- 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 +11 -1
- package/dist/tools/retainer-trace.js.map +1 -1
- package/dist/tools/round-audit.d.ts +66 -0
- package/dist/tools/round-audit.d.ts.map +1 -0
- package/dist/tools/round-audit.js +258 -0
- package/dist/tools/round-audit.js.map +1 -0
- package/dist/tools/round-digest.d.ts +12 -0
- package/dist/tools/round-digest.d.ts.map +1 -0
- package/dist/tools/round-digest.js +190 -0
- package/dist/tools/round-digest.js.map +1 -0
- package/dist/tools/script-census.d.ts +12 -0
- package/dist/tools/script-census.d.ts.map +1 -0
- package/dist/tools/script-census.js +182 -0
- package/dist/tools/script-census.js.map +1 -0
- package/dist/tools/sequence-analysis.d.ts +4 -0
- package/dist/tools/sequence-analysis.d.ts.map +1 -1
- package/dist/tools/sequence-analysis.js +53 -9
- package/dist/tools/sequence-analysis.js.map +1 -1
- package/dist/tools/server-status.d.ts.map +1 -1
- package/dist/tools/server-status.js +4 -1
- package/dist/tools/server-status.js.map +1 -1
- package/dist/tools/settle-check.d.ts +12 -0
- package/dist/tools/settle-check.d.ts.map +1 -0
- package/dist/tools/settle-check.js +188 -0
- package/dist/tools/settle-check.js.map +1 -0
- package/dist/tools/sliced-strings.d.ts.map +1 -1
- package/dist/tools/sliced-strings.js +2 -1
- package/dist/tools/sliced-strings.js.map +1 -1
- package/dist/tools/snapshots.d.ts.map +1 -1
- package/dist/tools/snapshots.js +24 -6
- package/dist/tools/snapshots.js.map +1 -1
- package/dist/tools/sparse-elements.d.ts +12 -0
- package/dist/tools/sparse-elements.d.ts.map +1 -0
- package/dist/tools/sparse-elements.js +215 -0
- package/dist/tools/sparse-elements.js.map +1 -0
- package/dist/tools/stale-collections.d.ts +17 -0
- package/dist/tools/stale-collections.d.ts.map +1 -1
- package/dist/tools/stale-collections.js +28 -0
- package/dist/tools/stale-collections.js.map +1 -1
- package/dist/tools/string-patterns.d.ts.map +1 -1
- package/dist/tools/string-patterns.js +2 -1
- package/dist/tools/string-patterns.js.map +1 -1
- package/dist/tools/tools-index.d.ts.map +1 -1
- package/dist/tools/tools-index.js +155 -5
- package/dist/tools/tools-index.js.map +1 -1
- package/dist/tools/trace-all.d.ts +42 -0
- package/dist/tools/trace-all.d.ts.map +1 -0
- package/dist/tools/trace-all.js +263 -0
- package/dist/tools/trace-all.js.map +1 -0
- package/dist/tools/unit-cost.d.ts +12 -0
- package/dist/tools/unit-cost.d.ts.map +1 -0
- package/dist/tools/unit-cost.js +219 -0
- package/dist/tools/unit-cost.js.map +1 -0
- package/dist/tools/verify-fix.d.ts.map +1 -1
- package/dist/tools/verify-fix.js +11 -3
- package/dist/tools/verify-fix.js.map +1 -1
- package/dist/tools/weakref-census.d.ts +15 -0
- package/dist/tools/weakref-census.d.ts.map +1 -0
- package/dist/tools/weakref-census.js +147 -0
- package/dist/tools/weakref-census.js.map +1 -0
- package/dist/tools/what-if.d.ts +12 -0
- package/dist/tools/what-if.d.ts.map +1 -0
- package/dist/tools/what-if.js +285 -0
- package/dist/tools/what-if.js.map +1 -0
- package/dist/utils.d.ts +92 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +172 -5
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"census-diff.js","sourceRoot":"","sources":["../../src/tools/census-diff.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 registerChainWalk(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=chain-walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-walk.d.ts","sourceRoot":"","sources":["../../src/tools/chain-walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAgCvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4NzD"}
|
|
@@ -0,0 +1,184 @@
|
|
|
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 { toolResult, formatBytes, formatNumber } from '../utils.js';
|
|
13
|
+
export function registerChainWalk(server) {
|
|
14
|
+
server.tool('memlab_chain_walk', 'Walk a repeated linked structure from a starting node and report how deep it goes and what it holds — for closure chains (`begin` -> `context` -> `.prev` -> ...), React update queues (`.next`), LRU lists (`.next`/`.prev`), and range/interval trees (`.l`/`.r`). ' +
|
|
15
|
+
'Exists because these get hand-written as evals, and the hand-written version reliably miscounts: it counts how many TIMES an object is captured rather than how many DISTINCT objects are captured, so a chain that pins the same element at several links reads as that many separate leaks. Measured case: a hand-rolled walk reported 6 distinct detached elements for a 6-link chain that pinned 2. ' +
|
|
16
|
+
'This returns distinct sets by construction and reports the occurrence count alongside only when the two differ. Cycles are detected and reported rather than walked forever. ' +
|
|
17
|
+
'Use it after a retainer trace shows the same edge name repeating — that repetition is the signal that a chain, not a single object, is the finding.', {
|
|
18
|
+
start_id: z
|
|
19
|
+
.number()
|
|
20
|
+
.describe('Node id to start from (the object holding the chain head).'),
|
|
21
|
+
head_edge: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Optional edge to step through first, from `start_id` to the first link (e.g. "begin"). Omit if `start_id` IS the first link.'),
|
|
25
|
+
next_edges: z
|
|
26
|
+
.array(z.string())
|
|
27
|
+
.min(1)
|
|
28
|
+
.describe('Edge name(s) that advance one link. One name walks a list ("next", "prev", "p"); several walk a tree ("l", "r"), in which case every branch is followed and `depth` is the maximum depth reached.'),
|
|
29
|
+
capture_edges: z
|
|
30
|
+
.array(z.string())
|
|
31
|
+
.optional()
|
|
32
|
+
.default([])
|
|
33
|
+
.describe('Edges to record at each link — what the chain is holding onto. Omit to record every named property of each link, which is the right default when you do not yet know what it captures.'),
|
|
34
|
+
max_links: z
|
|
35
|
+
.number()
|
|
36
|
+
.optional()
|
|
37
|
+
.default(10000)
|
|
38
|
+
.describe('Safety bound on links visited (default 10000). A chain longer than this is itself the finding; the result says it was truncated.'),
|
|
39
|
+
show_links: z
|
|
40
|
+
.number()
|
|
41
|
+
.optional()
|
|
42
|
+
.default(3)
|
|
43
|
+
.describe('How many individual links to detail (default 3).'),
|
|
44
|
+
}, async ({ start_id, head_edge, next_edges, capture_edges, max_links, show_links, }) => {
|
|
45
|
+
const snapshot = getSnapshot();
|
|
46
|
+
if (!snapshot) {
|
|
47
|
+
return toolResult('Error: No heap snapshot loaded. Use memlab_load_snapshot first.');
|
|
48
|
+
}
|
|
49
|
+
const start = snapshot.getNodeById(start_id);
|
|
50
|
+
if (!start) {
|
|
51
|
+
return toolResult(`Error: node @${start_id} not found.`);
|
|
52
|
+
}
|
|
53
|
+
const edgeTarget = (node, name) => {
|
|
54
|
+
for (const e of node.references) {
|
|
55
|
+
if (String(e.name_or_index) === name)
|
|
56
|
+
return e.toNode;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
};
|
|
60
|
+
let head = start;
|
|
61
|
+
if (head_edge != null && head_edge !== '') {
|
|
62
|
+
head = edgeTarget(start, head_edge);
|
|
63
|
+
if (!head) {
|
|
64
|
+
return toolResult(`Error: @${start_id} has no edge \`${head_edge}\`. Check the edge name with memlab_object_shape({node_id: ${start_id}}).`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
const links = [];
|
|
69
|
+
// Distinct captured objects across the WHOLE chain — the number that is
|
|
70
|
+
// usually wanted and usually got wrong.
|
|
71
|
+
const distinctCaptured = new Map();
|
|
72
|
+
let occurrences = 0;
|
|
73
|
+
let cyclic = false;
|
|
74
|
+
let truncated = false;
|
|
75
|
+
let maxDepth = 0;
|
|
76
|
+
const stack = [
|
|
77
|
+
{ node: head, depth: 1 },
|
|
78
|
+
];
|
|
79
|
+
while (stack.length > 0) {
|
|
80
|
+
const entry = stack.pop();
|
|
81
|
+
if (!entry)
|
|
82
|
+
break;
|
|
83
|
+
const { node, depth } = entry;
|
|
84
|
+
if (seen.has(node.id)) {
|
|
85
|
+
cyclic = true;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (seen.size >= max_links) {
|
|
89
|
+
truncated = true;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
seen.add(node.id);
|
|
93
|
+
maxDepth = Math.max(maxDepth, depth);
|
|
94
|
+
const captured = [];
|
|
95
|
+
for (const e of node.references) {
|
|
96
|
+
const edgeName = String(e.name_or_index);
|
|
97
|
+
if (next_edges.includes(edgeName))
|
|
98
|
+
continue;
|
|
99
|
+
const wanted = capture_edges.length > 0
|
|
100
|
+
? capture_edges.includes(edgeName)
|
|
101
|
+
: e.type === 'property' || e.type === 'context';
|
|
102
|
+
if (!wanted)
|
|
103
|
+
continue;
|
|
104
|
+
const t = e.toNode;
|
|
105
|
+
captured.push({
|
|
106
|
+
edge: edgeName,
|
|
107
|
+
id: t.id,
|
|
108
|
+
name: t.name,
|
|
109
|
+
detached: Boolean(t.is_detached),
|
|
110
|
+
});
|
|
111
|
+
occurrences++;
|
|
112
|
+
const prev = distinctCaptured.get(t.id);
|
|
113
|
+
if (prev) {
|
|
114
|
+
prev.occurrences++;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
distinctCaptured.set(t.id, {
|
|
118
|
+
name: t.name,
|
|
119
|
+
detached: Boolean(t.is_detached),
|
|
120
|
+
occurrences: 1,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (links.length < show_links) {
|
|
125
|
+
links.push({
|
|
126
|
+
depth,
|
|
127
|
+
nodeId: node.id,
|
|
128
|
+
name: node.name,
|
|
129
|
+
retained: node.retainedSize,
|
|
130
|
+
captured: captured.slice(0, 8),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
for (const edgeName of next_edges) {
|
|
134
|
+
const nxt = edgeTarget(node, edgeName);
|
|
135
|
+
if (nxt)
|
|
136
|
+
stack.push({ node: nxt, depth: depth + 1 });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const detachedDistinct = [...distinctCaptured.values()].filter(c => c.detached).length;
|
|
140
|
+
const out = [
|
|
141
|
+
`## Chain from @${start_id}${head_edge ? ` via \`.${head_edge}\`` : ''}`,
|
|
142
|
+
'',
|
|
143
|
+
`- **Links walked: ${formatNumber(seen.size)}** (max depth ${formatNumber(maxDepth)})`,
|
|
144
|
+
`- Distinct objects captured: **${formatNumber(distinctCaptured.size)}**` +
|
|
145
|
+
(occurrences !== distinctCaptured.size
|
|
146
|
+
? ` — from ${formatNumber(occurrences)} capture occurrences, so the same object is held at several links. Quote the DISTINCT count; the occurrence count is what a hand-written walk reports by mistake.`
|
|
147
|
+
: ''),
|
|
148
|
+
`- Distinct captured objects that are detached DOM: **${formatNumber(detachedDistinct)}**`,
|
|
149
|
+
];
|
|
150
|
+
if (cyclic) {
|
|
151
|
+
out.push('- ⚠ The chain revisits a node it already walked: it is cyclic, not a list. Depth is the number of distinct links, not a loop count.');
|
|
152
|
+
}
|
|
153
|
+
if (truncated) {
|
|
154
|
+
out.push(`- ⚠ Stopped at the ${formatNumber(max_links)}-link bound; the real chain is longer. That length is itself the finding.`);
|
|
155
|
+
}
|
|
156
|
+
if (seen.size === 1) {
|
|
157
|
+
out.push('', `> Only one link: nothing advanced through ${next_edges.map(e => `\`${e}\``).join(' / ')}. Either this is not a chain, or the advancing edge has a different name — check with memlab_object_shape({node_id: ${start_id}}).`);
|
|
158
|
+
}
|
|
159
|
+
if (links.length > 0) {
|
|
160
|
+
out.push('', '### First links', '');
|
|
161
|
+
for (const l of links) {
|
|
162
|
+
out.push(`**Link ${l.depth}** — @${l.nodeId} \`${l.name}\` (${formatBytes(l.retained)} retained)`);
|
|
163
|
+
if (l.captured.length === 0) {
|
|
164
|
+
out.push(' - captures nothing named');
|
|
165
|
+
}
|
|
166
|
+
for (const c of l.captured) {
|
|
167
|
+
out.push(` - \`${c.edge}\` → @${c.id} ${c.name}${c.detached ? ' **[DETACHED]**' : ''}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const top = [...distinctCaptured.entries()]
|
|
172
|
+
.sort((a, b) => b[1].occurrences - a[1].occurrences)
|
|
173
|
+
.slice(0, 8);
|
|
174
|
+
if (top.length > 0) {
|
|
175
|
+
out.push('', '### Distinct captured objects (most-held first)', '');
|
|
176
|
+
for (const [nodeId, info] of top) {
|
|
177
|
+
out.push(`- @${nodeId} \`${info.name}\`${info.detached ? ' **[DETACHED]**' : ''} — held at ${formatNumber(info.occurrences)} link(s)`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
out.push('', "_Depth alone is not a leak: a bounded structure has a depth too. What makes a chain a finding is that it grows per interaction and nothing removes links — check that with `memlab_ladder_probe` over a ladder, using this tool's link count as the metric._");
|
|
181
|
+
return toolResult(out.join('\n'));
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=chain-walk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-walk.js","sourceRoot":"","sources":["../../src/tools/chain-walk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
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 { IHeapNode, IHeapSnapshot } from '@memlab/core';
|
|
11
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
12
|
+
/**
|
|
13
|
+
* A per-capture-stable name for one collection, in the SAME `<Owner>.<property>`
|
|
14
|
+
* form `memlab_collection_trend` takes as a locator.
|
|
15
|
+
*
|
|
16
|
+
* That shared shape is the point of this tool: discovery hands you a locator you
|
|
17
|
+
* can paste straight into the trend tool to confirm and to track a fix, instead
|
|
18
|
+
* of a node id that means nothing in the next capture.
|
|
19
|
+
*
|
|
20
|
+
* Node ids, array indices and V8 scope numbers are all per-capture, so none of
|
|
21
|
+
* them can appear in the signature. The walk climbs referrers (not the dominator
|
|
22
|
+
* tree — this runs on a LIGHT parse with no dominators) until it finds a class
|
|
23
|
+
* name worth printing, and falls back to `<context>` for a module-scope closure
|
|
24
|
+
* binding, which is where most module singletons live.
|
|
25
|
+
*/
|
|
26
|
+
export declare function collectionSignature(node: IHeapNode): string | null;
|
|
27
|
+
export interface CollectionStat {
|
|
28
|
+
instances: number;
|
|
29
|
+
entries: number;
|
|
30
|
+
maxEntries: number;
|
|
31
|
+
kinds: Set<string>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Census every JS collection in one snapshot, keyed by signature.
|
|
35
|
+
*
|
|
36
|
+
* Deliberately does NOT filter by size. The whole point is to catch the
|
|
37
|
+
* collection that is small now and unbounded later: one of the three
|
|
38
|
+
* never-drained telemetry stores this tool was written for held 2 entries at the
|
|
39
|
+
* baseline rung and 1,260 at the last one, so any size floor would have hidden
|
|
40
|
+
* it. Growth is the filter, and growth needs the ladder.
|
|
41
|
+
*/
|
|
42
|
+
export declare function censusCollections(snapshot: IHeapSnapshot): Map<string, CollectionStat>;
|
|
43
|
+
export declare function registerCollectionDiff(server: McpServer): void;
|
|
44
|
+
//# sourceMappingURL=collection-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-diff.d.ts","sourceRoot":"","sources":["../../src/tools/collection-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAY,SAAS,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA6DvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAsDlE;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,GACtB,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAoB7B;AAkDD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2K9D"}
|
|
@@ -0,0 +1,343 @@
|
|
|
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 fs from 'fs';
|
|
11
|
+
import memlabCore from '@memlab/core';
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { errorResult, formatNumber, markdownTable, pathsHeader, toolResult, } from '../utils.js';
|
|
14
|
+
import { countEntries } from './collection-trend.js';
|
|
15
|
+
import { resolveLadderPaths } from './ladder.js';
|
|
16
|
+
import { resolveMaxFileSizeMB, resolveSnapshotPath } from './load-snapshot.js';
|
|
17
|
+
const { utils: memlabUtils } = memlabCore;
|
|
18
|
+
/**
|
|
19
|
+
* Class names that carry no information as an owner label. A signature built on
|
|
20
|
+
* one of these is not distinguishable from thousands of others, so the walk
|
|
21
|
+
* keeps climbing to find something nameable.
|
|
22
|
+
*/
|
|
23
|
+
const GENERIC_OWNER_NAMES = new Set([
|
|
24
|
+
'',
|
|
25
|
+
'Object',
|
|
26
|
+
'Array',
|
|
27
|
+
'Map',
|
|
28
|
+
'Set',
|
|
29
|
+
'WeakMap',
|
|
30
|
+
'WeakSet',
|
|
31
|
+
'(object elements)',
|
|
32
|
+
'(object properties)',
|
|
33
|
+
]);
|
|
34
|
+
/** JS-level collections a caller can actually act on. */
|
|
35
|
+
const COLLECTION_CLASS_NAMES = new Set([
|
|
36
|
+
'Map',
|
|
37
|
+
'Set',
|
|
38
|
+
'WeakMap',
|
|
39
|
+
'WeakSet',
|
|
40
|
+
'Array',
|
|
41
|
+
]);
|
|
42
|
+
const MAX_OWNER_HOPS = 4;
|
|
43
|
+
function isGenericOwner(name) {
|
|
44
|
+
if (GENERIC_OWNER_NAMES.has(name))
|
|
45
|
+
return true;
|
|
46
|
+
// `system / Context / scope @805823` — the scope id is per-capture, so the
|
|
47
|
+
// name is both generic AND unstable. Collapsed to `<context>` below.
|
|
48
|
+
if (name.startsWith('system / Context'))
|
|
49
|
+
return true;
|
|
50
|
+
if (name.startsWith('system /'))
|
|
51
|
+
return true;
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
function edgeLabel(edge) {
|
|
55
|
+
const raw = String(edge.name_or_index);
|
|
56
|
+
if (raw === '' || /^\d+$/.test(raw))
|
|
57
|
+
return null;
|
|
58
|
+
if (raw === '__proto__' || raw === 'map' || raw === 'elements')
|
|
59
|
+
return null;
|
|
60
|
+
return raw;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A per-capture-stable name for one collection, in the SAME `<Owner>.<property>`
|
|
64
|
+
* form `memlab_collection_trend` takes as a locator.
|
|
65
|
+
*
|
|
66
|
+
* That shared shape is the point of this tool: discovery hands you a locator you
|
|
67
|
+
* can paste straight into the trend tool to confirm and to track a fix, instead
|
|
68
|
+
* of a node id that means nothing in the next capture.
|
|
69
|
+
*
|
|
70
|
+
* Node ids, array indices and V8 scope numbers are all per-capture, so none of
|
|
71
|
+
* them can appear in the signature. The walk climbs referrers (not the dominator
|
|
72
|
+
* tree — this runs on a LIGHT parse with no dominators) until it finds a class
|
|
73
|
+
* name worth printing, and falls back to `<context>` for a module-scope closure
|
|
74
|
+
* binding, which is where most module singletons live.
|
|
75
|
+
*/
|
|
76
|
+
export function collectionSignature(node) {
|
|
77
|
+
let binding = null;
|
|
78
|
+
let owner = null;
|
|
79
|
+
// Prefer a `property` binding, then a closure `context` binding; both name the
|
|
80
|
+
// field the collection is stored in, which is what a reader needs.
|
|
81
|
+
for (const pass of ['property', 'context', 'any']) {
|
|
82
|
+
for (const edge of node.referrers) {
|
|
83
|
+
if (pass !== 'any' && edge.type !== pass)
|
|
84
|
+
continue;
|
|
85
|
+
if (edge.type === 'hidden' || edge.type === 'internal')
|
|
86
|
+
continue;
|
|
87
|
+
const label = edgeLabel(edge);
|
|
88
|
+
if (label == null)
|
|
89
|
+
continue;
|
|
90
|
+
const from = edge.fromNode;
|
|
91
|
+
if (from == null || from.id <= 3)
|
|
92
|
+
continue;
|
|
93
|
+
binding = label;
|
|
94
|
+
owner = from;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
if (binding != null)
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
if (binding == null || owner == null)
|
|
101
|
+
return null;
|
|
102
|
+
// Climb until the owner has a name worth printing.
|
|
103
|
+
let hops = 0;
|
|
104
|
+
const prefixParts = [];
|
|
105
|
+
let cur = owner;
|
|
106
|
+
while (cur != null && hops < MAX_OWNER_HOPS && isGenericOwner(cur.name)) {
|
|
107
|
+
let next = null;
|
|
108
|
+
let nextLabel = null;
|
|
109
|
+
for (const edge of cur.referrers) {
|
|
110
|
+
if (edge.type === 'hidden' || edge.type === 'internal')
|
|
111
|
+
continue;
|
|
112
|
+
const label = edgeLabel(edge);
|
|
113
|
+
if (label == null)
|
|
114
|
+
continue;
|
|
115
|
+
const from = edge.fromNode ?? null;
|
|
116
|
+
if (from == null || from.id <= 3)
|
|
117
|
+
continue;
|
|
118
|
+
next = from;
|
|
119
|
+
nextLabel = label;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
if (next == null)
|
|
123
|
+
break;
|
|
124
|
+
if (nextLabel != null)
|
|
125
|
+
prefixParts.unshift(nextLabel);
|
|
126
|
+
cur = next;
|
|
127
|
+
hops++;
|
|
128
|
+
}
|
|
129
|
+
let ownerLabel;
|
|
130
|
+
if (cur == null) {
|
|
131
|
+
ownerLabel = 'Object';
|
|
132
|
+
}
|
|
133
|
+
else if (cur.name.startsWith('system / Context')) {
|
|
134
|
+
ownerLabel = '<context>';
|
|
135
|
+
}
|
|
136
|
+
else if (isGenericOwner(cur.name)) {
|
|
137
|
+
ownerLabel = cur.name.length > 0 ? cur.name : 'Object';
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
ownerLabel = cur.name;
|
|
141
|
+
}
|
|
142
|
+
return [ownerLabel, ...prefixParts, binding].join('.');
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Census every JS collection in one snapshot, keyed by signature.
|
|
146
|
+
*
|
|
147
|
+
* Deliberately does NOT filter by size. The whole point is to catch the
|
|
148
|
+
* collection that is small now and unbounded later: one of the three
|
|
149
|
+
* never-drained telemetry stores this tool was written for held 2 entries at the
|
|
150
|
+
* baseline rung and 1,260 at the last one, so any size floor would have hidden
|
|
151
|
+
* it. Growth is the filter, and growth needs the ladder.
|
|
152
|
+
*/
|
|
153
|
+
export function censusCollections(snapshot) {
|
|
154
|
+
const out = new Map();
|
|
155
|
+
snapshot.nodes.forEach((node) => {
|
|
156
|
+
if (node.id <= 3)
|
|
157
|
+
return;
|
|
158
|
+
if (!COLLECTION_CLASS_NAMES.has(node.name))
|
|
159
|
+
return;
|
|
160
|
+
const n = countEntries(node);
|
|
161
|
+
if (n == null || n === 0)
|
|
162
|
+
return;
|
|
163
|
+
const sig = collectionSignature(node);
|
|
164
|
+
if (sig == null)
|
|
165
|
+
return;
|
|
166
|
+
let s = out.get(sig);
|
|
167
|
+
if (!s) {
|
|
168
|
+
s = { instances: 0, entries: 0, maxEntries: 0, kinds: new Set() };
|
|
169
|
+
out.set(sig, s);
|
|
170
|
+
}
|
|
171
|
+
s.instances++;
|
|
172
|
+
s.entries += n;
|
|
173
|
+
if (n > s.maxEntries)
|
|
174
|
+
s.maxEntries = n;
|
|
175
|
+
s.kinds.add(node.name);
|
|
176
|
+
});
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
function buildRows(perRung, minGrowth) {
|
|
180
|
+
const sigs = new Set();
|
|
181
|
+
for (const m of perRung)
|
|
182
|
+
for (const k of m.keys())
|
|
183
|
+
sigs.add(k);
|
|
184
|
+
const rows = [];
|
|
185
|
+
for (const sig of sigs) {
|
|
186
|
+
const series = perRung.map(m => m.get(sig)?.entries ?? 0);
|
|
187
|
+
const instances = perRung.map(m => m.get(sig)?.instances ?? 0);
|
|
188
|
+
const delta = series[series.length - 1] - series[0];
|
|
189
|
+
if (delta < minGrowth)
|
|
190
|
+
continue;
|
|
191
|
+
let monotonic = true;
|
|
192
|
+
for (let i = 1; i < series.length; i++) {
|
|
193
|
+
if (series[i] <= series[i - 1])
|
|
194
|
+
monotonic = false;
|
|
195
|
+
}
|
|
196
|
+
const kinds = new Set();
|
|
197
|
+
for (const m of perRung) {
|
|
198
|
+
const s = m.get(sig);
|
|
199
|
+
if (s)
|
|
200
|
+
for (const k of s.kinds)
|
|
201
|
+
kinds.add(k);
|
|
202
|
+
}
|
|
203
|
+
rows.push({
|
|
204
|
+
sig,
|
|
205
|
+
kind: [...kinds].sort().join('/'),
|
|
206
|
+
series,
|
|
207
|
+
instances,
|
|
208
|
+
maxEntries: Math.max(...perRung.map(m => m.get(sig)?.maxEntries ?? 0)),
|
|
209
|
+
delta,
|
|
210
|
+
monotonic,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
rows.sort((a, b) => {
|
|
214
|
+
if (a.monotonic !== b.monotonic)
|
|
215
|
+
return a.monotonic ? -1 : 1;
|
|
216
|
+
return b.delta - a.delta;
|
|
217
|
+
});
|
|
218
|
+
return rows;
|
|
219
|
+
}
|
|
220
|
+
export function registerCollectionDiff(server) {
|
|
221
|
+
server.tool('memlab_collection_diff', 'Find WHICH collections grew across a snapshot ladder, WITHOUT being told their names. Censuses every Map/Set/WeakMap/WeakSet/Array on every rung, keys each by a per-capture-STABLE `<Owner>.<property>` signature, and diffs the entry counts. ' +
|
|
222
|
+
'This is the discovery half of memlab_collection_trend, which is excellent but requires a locator you must already know — so every accumulating collection had to be found first by hand-tracing a retainer path, and the ones nobody thought to trace were never found at all. ' +
|
|
223
|
+
'It is also the answer to the case the single-snapshot tools structurally cannot see: memlab_cache_analysis and memlab_growth_signals rank by SIZE on one rung, so they surface big-and-static collections and miss the small-but-unbounded one. This tool applies NO size floor — growth is the filter — because the store that matters most may hold 2 entries at the baseline. ' +
|
|
224
|
+
'The signatures it emits are valid memlab_collection_trend locators: confirm a candidate, and later verify a fix, by pasting one straight in. ' +
|
|
225
|
+
'Loads each rung transiently in LIGHT mode (one graph resident at a time), so it is safe on ladders too large to hold in memory at once.', {
|
|
226
|
+
paths: z
|
|
227
|
+
.array(z.string())
|
|
228
|
+
.min(1)
|
|
229
|
+
.describe('Ordered snapshot paths, OLDEST FIRST (>=2). A single ["ladder:<name>"] element expands to a saved ladder (see memlab_ladder).'),
|
|
230
|
+
cycles: z
|
|
231
|
+
.number()
|
|
232
|
+
.optional()
|
|
233
|
+
.describe('Interaction cycles driven between the FIRST and LAST rung. When given, a Δ/cycle column is reported — the per-cycle rate is what says whether a collection scales with interaction.'),
|
|
234
|
+
min_growth: z
|
|
235
|
+
.number()
|
|
236
|
+
.optional()
|
|
237
|
+
.default(20)
|
|
238
|
+
.describe('Only report collections whose total entry count grew by at least this across the ladder (default 20). This is a GROWTH floor, not a size floor — a collection that went 2 -> 1,260 is reported, one that sits flat at 9,356 is not.'),
|
|
239
|
+
limit: z
|
|
240
|
+
.number()
|
|
241
|
+
.optional()
|
|
242
|
+
.default(30)
|
|
243
|
+
.describe('Maximum number of collections to report (default 30).'),
|
|
244
|
+
monotonic_only: z
|
|
245
|
+
.boolean()
|
|
246
|
+
.optional()
|
|
247
|
+
.default(false)
|
|
248
|
+
.describe('Only report collections that grew at EVERY rung (default false: grew-net collections are included and flagged).'),
|
|
249
|
+
max_file_size_mb: z
|
|
250
|
+
.number()
|
|
251
|
+
.optional()
|
|
252
|
+
.describe('Per-file size limit override (MB).'),
|
|
253
|
+
}, async ({ paths, cycles, min_growth, limit, monotonic_only, max_file_size_mb, }) => {
|
|
254
|
+
try {
|
|
255
|
+
const { paths: resolved } = resolveLadderPaths(paths);
|
|
256
|
+
if (resolved.length < 2) {
|
|
257
|
+
return errorResult('memlab_collection_diff needs at least 2 snapshots — it diffs collection sizes across a ladder. For a single snapshot use memlab_cache_analysis or memlab_growth_signals.');
|
|
258
|
+
}
|
|
259
|
+
const labels = [];
|
|
260
|
+
const perRung = [];
|
|
261
|
+
for (const p of resolved) {
|
|
262
|
+
let local;
|
|
263
|
+
let fetchedFrom = null;
|
|
264
|
+
try {
|
|
265
|
+
const r = resolveSnapshotPath(p);
|
|
266
|
+
local = r.localPath;
|
|
267
|
+
fetchedFrom = r.fetchedFrom;
|
|
268
|
+
}
|
|
269
|
+
catch (e) {
|
|
270
|
+
return errorResult(`Failed to resolve "${p}": ${e instanceof Error ? e.message : String(e)}`);
|
|
271
|
+
}
|
|
272
|
+
if (!fs.existsSync(local)) {
|
|
273
|
+
return errorResult(`File not found: ${local}`);
|
|
274
|
+
}
|
|
275
|
+
const sizeMB = fs.statSync(local).size / (1024 * 1024);
|
|
276
|
+
const cap = resolveMaxFileSizeMB(max_file_size_mb, fetchedFrom != null);
|
|
277
|
+
if (sizeMB > cap) {
|
|
278
|
+
return errorResult(`${p} is ${sizeMB.toFixed(0)} MB — exceeds the ${cap} MB per-file safety limit. Raise it with max_file_size_mb: ${Math.ceil(sizeMB + 100)}.`);
|
|
279
|
+
}
|
|
280
|
+
const snapshot = await memlabUtils.getSnapshotFromFile(local, {
|
|
281
|
+
buildNodeIdIndex: true,
|
|
282
|
+
verbose: false,
|
|
283
|
+
});
|
|
284
|
+
labels.push(fetchedFrom ?? p.replace(/^.*\//, ''));
|
|
285
|
+
perRung.push(censusCollections(snapshot));
|
|
286
|
+
}
|
|
287
|
+
let rows = buildRows(perRung, min_growth);
|
|
288
|
+
if (monotonic_only)
|
|
289
|
+
rows = rows.filter(r => r.monotonic);
|
|
290
|
+
const shown = rows.slice(0, limit);
|
|
291
|
+
const perCycle = cycles != null && cycles > 0;
|
|
292
|
+
const lines = [
|
|
293
|
+
`## Collection diff across ${resolved.length} rung(s)`,
|
|
294
|
+
'',
|
|
295
|
+
];
|
|
296
|
+
if (shown.length === 0) {
|
|
297
|
+
lines.push(`No collection grew by ${formatNumber(min_growth)} or more entries across this ladder.`, '', '_That is a real negative for unbounded-collection growth specifically — it does not cover detached DOM, listener records, string accumulation or retained-size growth with a flat entry count. Lower `min_growth` to see smaller movers._');
|
|
298
|
+
return toolResult(lines.join('\n'), pathsHeader(labels));
|
|
299
|
+
}
|
|
300
|
+
const headers = [
|
|
301
|
+
'Collection (usable as a collection_trend locator)',
|
|
302
|
+
'Kind',
|
|
303
|
+
...labels.map((_, i) => `r${i}`),
|
|
304
|
+
'Δ',
|
|
305
|
+
...(perCycle ? ['Δ/cycle'] : []),
|
|
306
|
+
'Instances',
|
|
307
|
+
'Largest',
|
|
308
|
+
'Trend',
|
|
309
|
+
];
|
|
310
|
+
const right = new Set();
|
|
311
|
+
for (let i = 2; i < headers.length - 1; i++)
|
|
312
|
+
right.add(i);
|
|
313
|
+
const table = shown.map(r => [
|
|
314
|
+
r.sig.length > 52 ? r.sig.slice(0, 49) + '…' : r.sig,
|
|
315
|
+
r.kind,
|
|
316
|
+
...r.series.map(v => formatNumber(v)),
|
|
317
|
+
`+${formatNumber(r.delta)}`,
|
|
318
|
+
...(perCycle ? [(r.delta / cycles).toFixed(2)] : []),
|
|
319
|
+
`${formatNumber(r.instances[0])} → ${formatNumber(r.instances[r.instances.length - 1])}`,
|
|
320
|
+
formatNumber(r.maxEntries),
|
|
321
|
+
r.monotonic ? '↑ every rung' : 'grew net',
|
|
322
|
+
]);
|
|
323
|
+
lines.push(markdownTable(headers, table, right));
|
|
324
|
+
const mono = shown.filter(r => r.monotonic);
|
|
325
|
+
lines.push('', `**${formatNumber(mono.length)} of ${formatNumber(shown.length)} shown grew at EVERY rung** — monotonic growth under a repeated interaction is the signature of an unbounded collection.` +
|
|
326
|
+
(rows.length > shown.length
|
|
327
|
+
? ` ${formatNumber(rows.length - shown.length)} more above the growth floor were not shown (raise \`limit\`).`
|
|
328
|
+
: ''));
|
|
329
|
+
if (mono.length > 0) {
|
|
330
|
+
lines.push('', '**Next:** confirm one with the trend tool, which measures the same collection per rung and reports owners separately from entries:', '```', `memlab_collection_trend({paths: [...], locators: [${mono
|
|
331
|
+
.slice(0, 4)
|
|
332
|
+
.map(r => `"${r.sig}"`)
|
|
333
|
+
.join(', ')}]${perCycle ? `, cycles: ${cycles}` : ''}})`, '```', 'Then `memlab_retainer_trace` the owner to name what holds it, and check whether the entries are distinct rather than one object re-added.');
|
|
334
|
+
}
|
|
335
|
+
lines.push('', '_Instances is the count of DISTINCT collections sharing a signature. When instances grow but the largest single collection does not, the OWNERS are accumulating, not the collection — a different fix (stop minting owners) from bounding one container._', '_Signatures are structural, not identities: two unrelated collections bound to the same-named field of the same-named class share a row. The `Instances` column is what exposes that._');
|
|
336
|
+
return toolResult(lines.join('\n'), pathsHeader(labels));
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
return errorResult(`Failed to diff collections: ${error instanceof Error ? error.message : String(error)}`);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=collection-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-diff.js","sourceRoot":"","sources":["../../src/tools/collection-diff.ts"],"names":[],"mappings":"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"}
|