memorydetective 1.13.0 → 1.15.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +8 -2
  3. package/USAGE.md +29 -0
  4. package/dist/index.js +36 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/parsers/schemaDiscovery.d.ts +88 -0
  7. package/dist/parsers/schemaDiscovery.js +144 -0
  8. package/dist/parsers/schemaDiscovery.js.map +1 -0
  9. package/dist/parsers/xctraceXml.d.ts +5 -0
  10. package/dist/parsers/xctraceXml.js +3 -0
  11. package/dist/parsers/xctraceXml.js.map +1 -1
  12. package/dist/tools/analyzeAllocations.d.ts +5 -1
  13. package/dist/tools/analyzeAllocations.js +17 -1
  14. package/dist/tools/analyzeAllocations.js.map +1 -1
  15. package/dist/tools/analyzeAnimationHitches.d.ts +5 -1
  16. package/dist/tools/analyzeAnimationHitches.js +17 -1
  17. package/dist/tools/analyzeAnimationHitches.js.map +1 -1
  18. package/dist/tools/analyzeAppLaunch.d.ts +3 -0
  19. package/dist/tools/analyzeAppLaunch.js +17 -1
  20. package/dist/tools/analyzeAppLaunch.js.map +1 -1
  21. package/dist/tools/analyzeEnergyImpact.d.ts +69 -0
  22. package/dist/tools/analyzeEnergyImpact.js +239 -0
  23. package/dist/tools/analyzeEnergyImpact.js.map +1 -0
  24. package/dist/tools/analyzeHangs.d.ts +63 -3
  25. package/dist/tools/analyzeHangs.js +143 -19
  26. package/dist/tools/analyzeHangs.js.map +1 -1
  27. package/dist/tools/analyzeLeakTimeline.d.ts +75 -0
  28. package/dist/tools/analyzeLeakTimeline.js +213 -0
  29. package/dist/tools/analyzeLeakTimeline.js.map +1 -0
  30. package/dist/tools/analyzeMemoryFootprint.d.ts +72 -0
  31. package/dist/tools/analyzeMemoryFootprint.js +234 -0
  32. package/dist/tools/analyzeMemoryFootprint.js.map +1 -0
  33. package/dist/tools/analyzeNetworkActivity.d.ts +99 -0
  34. package/dist/tools/analyzeNetworkActivity.js +312 -0
  35. package/dist/tools/analyzeNetworkActivity.js.map +1 -0
  36. package/dist/tools/analyzeTimeProfile.d.ts +10 -1
  37. package/dist/tools/analyzeTimeProfile.js +63 -8
  38. package/dist/tools/analyzeTimeProfile.js.map +1 -1
  39. package/dist/tools/countAlive.d.ts +35 -1
  40. package/dist/tools/countAlive.js +124 -29
  41. package/dist/tools/countAlive.js.map +1 -1
  42. package/dist/tools/inspectTrace.js +124 -18
  43. package/dist/tools/inspectTrace.js.map +1 -1
  44. package/dist/tools/recordTimeProfile.d.ts +83 -0
  45. package/dist/tools/recordTimeProfile.js +135 -0
  46. package/dist/tools/recordTimeProfile.js.map +1 -1
  47. package/dist/tools/replayScenario.d.ts +20 -4
  48. package/dist/tools/replayScenario.js +66 -0
  49. package/dist/tools/replayScenario.js.map +1 -1
  50. package/dist/tools/summarizeTrace.d.ts +6 -3
  51. package/dist/tools/summarizeTrace.js +49 -2
  52. package/dist/tools/summarizeTrace.js.map +1 -1
  53. package/dist/tools/verifyFix.d.ts +27 -0
  54. package/dist/tools/verifyFix.js +78 -4
  55. package/dist/tools/verifyFix.js.map +1 -1
  56. package/dist/types.d.ts +28 -0
  57. package/package.json +2 -2
@@ -19,8 +19,14 @@ export const countAliveSchema = z.object({
19
19
  .boolean()
20
20
  .default(false)
21
21
  .describe("v1.12+. When true, also parse `leaks --referenceTree --groupByType --noContent` output and surface heap-wide instance counts alongside the cycle-side counts. Required to find classes on memgraphs where `leakCount: 0` and the abandoned-memory shape is what's interesting (e.g. orphaned KVO observers reachable from the global registry). Adds a second `leaks` invocation, run in parallel. Default false preserves v1.11 behavior."),
22
+ sortBy: z
23
+ .enum(["count", "totalBytes"])
24
+ .default("count")
25
+ .describe("v1.14+. Ranks the topN by either instance count (default, preserves v1.13 behavior) or total bytes (FLEX's 'Size' sort). totalBytes is `count * instanceSizeBytes` and is the right rank for 'where is my memory going?' investigations vs 'how many instances are alive?'. Per-class instanceSizeBytes + totalBytes are returned regardless of sort key."),
22
26
  });
23
- /** Pure: count node occurrences by exact className across the cycle forest. */
27
+ /** Pure: count node occurrences by exact className across the cycle forest.
28
+ * Backwards-compatible API; for v1.14 byte aggregation use
29
+ * {@link countByClassWithBytes}. */
24
30
  export function countByClass(report) {
25
31
  const counts = new Map();
26
32
  for (const { node } of walkCycles(report.cycles)) {
@@ -30,6 +36,30 @@ export function countByClass(report) {
30
36
  }
31
37
  return counts;
32
38
  }
39
+ /**
40
+ * Pure: aggregate occurrences AND bytes by exact className across the
41
+ * cycle forest. Each node's `instanceSize` is summed into `totalBytes`;
42
+ * the first non-zero `instanceSize` seen is recorded as the canonical
43
+ * `instanceSizeBytes` (ObjC classes are typically fixed-size, so the
44
+ * first value is representative). Nodes without a size annotation
45
+ * contribute to count but not bytes. v1.14.
46
+ */
47
+ export function countByClassWithBytes(report) {
48
+ const acc = new Map();
49
+ for (const { node } of walkCycles(report.cycles)) {
50
+ if (!node.className)
51
+ continue;
52
+ const cur = acc.get(node.className) ?? { count: 0, totalBytes: 0 };
53
+ cur.count += 1;
54
+ if (node.instanceSize != null) {
55
+ cur.totalBytes += node.instanceSize;
56
+ if (cur.instanceSizeBytes == null)
57
+ cur.instanceSizeBytes = node.instanceSize;
58
+ }
59
+ acc.set(node.className, cur);
60
+ }
61
+ return acc;
62
+ }
33
63
  /**
34
64
  * Spawn `leaks --referenceTree --groupByType --noContent` and parse the
35
65
  * stdout. Non-fatal on failure: returns empty array so the cycle-side
@@ -41,37 +71,64 @@ async function captureReferenceTreeCounts(path) {
41
71
  if (result.code !== 0 && result.code !== 1)
42
72
  return new Map();
43
73
  const entries = parseReferenceTreeText(result.stdout, 5000);
44
- return new Map(entries.map((e) => [e.className, e.instanceCount]));
74
+ return new Map(entries.map((e) => [
75
+ e.className,
76
+ { count: e.instanceCount, totalBytes: e.totalBytes },
77
+ ]));
45
78
  }
46
79
  export async function countAlive(input) {
47
80
  const wantReferenceTree = input.includeReferenceTree ?? false;
81
+ const sortBy = input.sortBy ?? "count";
48
82
  const [{ report, resolvedPath }, refTreeCounts] = await Promise.all([
49
83
  runLeaksAndParse(input.path),
50
84
  wantReferenceTree
51
85
  ? captureReferenceTreeCounts(input.path)
52
86
  : Promise.resolve(new Map()),
53
87
  ]);
54
- const cycleCounts = countByClass(report);
55
- const totalNodes = Array.from(cycleCounts.values()).reduce((a, b) => a + b, 0);
88
+ const cycleByClass = countByClassWithBytes(report);
89
+ const totalNodes = Array.from(cycleByClass.values()).reduce((a, b) => a + b.count, 0);
56
90
  if (input.className) {
57
91
  let cycleMatched = 0;
58
- for (const [name, n] of cycleCounts.entries()) {
59
- if (name.includes(input.className))
60
- cycleMatched += n;
92
+ let cycleBytesMatched = 0;
93
+ let cycleInstanceSize;
94
+ for (const [name, info] of cycleByClass.entries()) {
95
+ if (!name.includes(input.className))
96
+ continue;
97
+ cycleMatched += info.count;
98
+ cycleBytesMatched += info.totalBytes;
99
+ if (cycleInstanceSize == null && info.instanceSizeBytes != null) {
100
+ cycleInstanceSize = info.instanceSizeBytes;
101
+ }
61
102
  }
62
103
  let refTreeMatched = 0;
63
- for (const [name, n] of refTreeCounts.entries()) {
64
- if (name.includes(input.className))
65
- refTreeMatched += n;
104
+ let refTreeBytesMatched = 0;
105
+ for (const [name, info] of refTreeCounts.entries()) {
106
+ if (!name.includes(input.className))
107
+ continue;
108
+ refTreeMatched += info.count;
109
+ refTreeBytesMatched += info.totalBytes;
66
110
  }
111
+ const totalCount = cycleMatched + refTreeMatched;
112
+ const totalBytes = cycleBytesMatched + refTreeBytesMatched;
113
+ const instanceSizeBytes = cycleInstanceSize ??
114
+ (totalCount > 0 && totalBytes > 0
115
+ ? Math.round(totalBytes / totalCount)
116
+ : undefined);
67
117
  const entry = wantReferenceTree
68
118
  ? {
69
119
  className: input.className,
70
- instanceCount: cycleMatched + refTreeMatched,
120
+ instanceCount: totalCount,
71
121
  byCycle: cycleMatched,
72
122
  byReferenceTree: refTreeMatched,
123
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
124
+ ...(totalBytes > 0 ? { totalBytes } : {}),
73
125
  }
74
- : { className: input.className, instanceCount: cycleMatched };
126
+ : {
127
+ className: input.className,
128
+ instanceCount: cycleMatched,
129
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
130
+ ...(cycleBytesMatched > 0 ? { totalBytes: cycleBytesMatched } : {}),
131
+ };
75
132
  return {
76
133
  ok: true,
77
134
  path: resolvedPath,
@@ -80,31 +137,69 @@ export async function countAlive(input) {
80
137
  };
81
138
  }
82
139
  // topN path. Merge cycle + reference-tree counts when the flag is on,
83
- // ordered by instanceCount desc.
140
+ // ordered by sortBy (default 'count', or 'totalBytes' for FLEX-style
141
+ // memory-budget rank).
84
142
  const merged = new Map();
85
- for (const [name, n] of cycleCounts.entries()) {
86
- merged.set(name, { byCycle: n, byReferenceTree: 0 });
143
+ for (const [name, info] of cycleByClass.entries()) {
144
+ merged.set(name, {
145
+ byCycle: info.count,
146
+ byReferenceTree: 0,
147
+ cycleBytes: info.totalBytes,
148
+ refTreeBytes: 0,
149
+ ...(info.instanceSizeBytes != null
150
+ ? { instanceSizeBytes: info.instanceSizeBytes }
151
+ : {}),
152
+ });
87
153
  }
88
154
  if (wantReferenceTree) {
89
- for (const [name, n] of refTreeCounts.entries()) {
155
+ for (const [name, info] of refTreeCounts.entries()) {
90
156
  const existing = merged.get(name);
91
- if (existing)
92
- existing.byReferenceTree = n;
93
- else
94
- merged.set(name, { byCycle: 0, byReferenceTree: n });
157
+ if (existing) {
158
+ existing.byReferenceTree = info.count;
159
+ existing.refTreeBytes = info.totalBytes;
160
+ }
161
+ else {
162
+ merged.set(name, {
163
+ byCycle: 0,
164
+ byReferenceTree: info.count,
165
+ cycleBytes: 0,
166
+ refTreeBytes: info.totalBytes,
167
+ });
168
+ }
95
169
  }
96
170
  }
97
171
  const topN = input.topN ?? 20;
98
- const allEntries = Array.from(merged.entries())
99
- .map(([name, v]) => wantReferenceTree
100
- ? {
101
- className: name,
102
- instanceCount: v.byCycle + v.byReferenceTree,
103
- byCycle: v.byCycle,
104
- byReferenceTree: v.byReferenceTree,
172
+ const allEntries = Array.from(merged.entries()).map(([name, v]) => {
173
+ const totalCount = v.byCycle + v.byReferenceTree;
174
+ const totalBytes = v.cycleBytes + v.refTreeBytes;
175
+ const instanceSizeBytes = v.instanceSizeBytes ??
176
+ (totalCount > 0 && totalBytes > 0
177
+ ? Math.round(totalBytes / totalCount)
178
+ : undefined);
179
+ return wantReferenceTree
180
+ ? {
181
+ className: name,
182
+ instanceCount: totalCount,
183
+ byCycle: v.byCycle,
184
+ byReferenceTree: v.byReferenceTree,
185
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
186
+ ...(totalBytes > 0 ? { totalBytes } : {}),
187
+ }
188
+ : {
189
+ className: name,
190
+ instanceCount: v.byCycle,
191
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
192
+ ...(v.cycleBytes > 0 ? { totalBytes: v.cycleBytes } : {}),
193
+ };
194
+ });
195
+ allEntries.sort((a, b) => {
196
+ if (sortBy === "totalBytes") {
197
+ const ad = (b.totalBytes ?? 0) - (a.totalBytes ?? 0);
198
+ if (ad !== 0)
199
+ return ad;
105
200
  }
106
- : { className: name, instanceCount: v.byCycle })
107
- .sort((a, b) => b.instanceCount - a.instanceCount);
201
+ return b.instanceCount - a.instanceCount;
202
+ });
108
203
  const top = allEntries.slice(0, topN);
109
204
  const result = {
110
205
  ok: true,
@@ -1 +1 @@
1
- {"version":3,"file":"countAlive.js","sourceRoot":"","sources":["../../src/tools/countAlive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAGrC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IACxE,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,mIAAmI,CACpI;IACH,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CACP,iFAAiF,CAClF;IACH,oBAAoB,EAAE,CAAC;SACpB,OAAO,EAAE;SACT,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CACP,4aAA4a,CAC7a;CACJ,CAAC,CAAC;AA8BH,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,SAAS;QAC9B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,0BAA0B,CACvC,IAAY;IAEZ,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,OAAO,EACP,CAAC,iBAAiB,EAAE,eAAe,EAAE,aAAa,EAAE,IAAI,CAAC,EACzD,EAAE,SAAS,EAAE,CAAC,GAAG,MAAM,EAAE,CAC1B,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAC7D,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5D,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAsB;IAEtB,MAAM,iBAAiB,GAAG,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC;IAC9D,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAClE,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;QAC5B,iBAAiB;YACf,CAAC,CAAC,0BAA0B,CAAC,KAAK,CAAC,IAAI,CAAC;YACxC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,GAAG,EAAkB,CAAC;KAC/C,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CACxD,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EACf,CAAC,CACF,CAAC;IAEF,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,YAAY,IAAI,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,cAAc,IAAI,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,KAAK,GAAoB,iBAAiB;YAC9C,CAAC,CAAC;gBACE,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,aAAa,EAAE,YAAY,GAAG,cAAc;gBAC5C,OAAO,EAAE,YAAY;gBACrB,eAAe,EAAE,cAAc;aAChC;YACH,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;QAChE,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,YAAY;YAClB,UAAU;YACV,MAAM,EAAE,CAAC,KAAK,CAAC;SAChB,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,iCAAiC;IACjC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwD,CAAC;IAC/E,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,iBAAiB,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,QAAQ;gBAAE,QAAQ,CAAC,eAAe,GAAG,CAAC,CAAC;;gBACtC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;SAC5C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,iBAAiB;QACf,CAAC,CAAC;YACE,SAAS,EAAE,IAAI;YACf,aAAa,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,eAAe;YAC5C,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,eAAe,EAAE,CAAC,CAAC,eAAe;SACnC;QACH,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAClD;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAqB;QAC/B,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,YAAY;QAClB,UAAU;QACV,MAAM,EAAE,GAAG;KACZ,CAAC;IAEF,wEAAwE;IACxE,uEAAuE;IACvE,+DAA+D;IAC/D,sCAAsC;IACtC,IAAI,iBAAiB,IAAI,aAAa,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,UAAU;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;aAC7C,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAClB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,gBAAgB,GAAG,UAAU,CAAC;QACvC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"countAlive.js","sourceRoot":"","sources":["../../src/tools/countAlive.ts"],"names":[],"mappings":"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"}
@@ -62,6 +62,22 @@ const SCHEMA_TO_ANALYZER = {
62
62
  tool: "analyzeAppLaunch",
63
63
  description: "Returns cold/warm launch type plus per-phase breakdown (process-creation, dyld-init, ObjC-init, AppDelegate, first-frame).",
64
64
  },
65
+ "network-connections": {
66
+ tool: "analyzeNetworkActivity",
67
+ description: "Per-request URL / host / method / status / response time / bytes. Top-N by duration and by bytes plus per-host aggregates.",
68
+ },
69
+ "memory-footprint": {
70
+ tool: "analyzeMemoryFootprint",
71
+ description: "Peak resident / dirty / virtual bytes plus per-sample timeline. The OOM-kill discriminator on iOS.",
72
+ },
73
+ "energy-impact": {
74
+ tool: "analyzeEnergyImpact",
75
+ description: "Per-sample bucket (idle / passive / active / high), aggregate wakeups, active ratio, top samples by energy cost.",
76
+ },
77
+ leaks: {
78
+ tool: "analyzeLeakTimeline",
79
+ description: "Time series of leak events: per-class first-seen-at, peak count, peak bytes, event count. Answers 'when did the leak appear?'.",
80
+ },
65
81
  };
66
82
  /** Pure: parse the trace-toc XML payload into an inspection result. */
67
83
  export function parseTraceToc(xml, tracePath) {
@@ -72,16 +88,22 @@ export function parseTraceToc(xml, tracePath) {
72
88
  // Surfacing only schema metadata + row counts is faster and avoids
73
89
  // pulling row payloads into memory for traces that have hundreds of
74
90
  // thousands of rows.
75
- // Match each <table schema="X"> block.
76
- const tableRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*>([\s\S]*?)<\/table>/g;
91
+ //
92
+ // Apple's `xctrace export --toc` emits self-closing `<table schema="X"/>`
93
+ // elements (the TOC carries column definitions only, no rows). Older
94
+ // synthetic fixtures and some xctrace versions use the open-close form
95
+ // `<table schema="X">...<row/>...</table>`. We match BOTH and fall back
96
+ // to row-counting from the body when present.
97
+ // Open-close form first: `<table schema="X">body</table>`.
98
+ const openCloseRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*>([\s\S]*?)<\/table>/g;
99
+ const seenRanges = [];
77
100
  let match;
78
- while ((match = tableRegex.exec(xml)) !== null) {
101
+ while ((match = openCloseRegex.exec(xml)) !== null) {
79
102
  const name = match[1];
80
103
  const body = match[2];
81
- // Row count = number of <row> tags inside this table.
104
+ seenRanges.push([match.index, match.index + match[0].length]);
82
105
  const rowMatches = body.match(/<row\b/g);
83
106
  const rowCount = rowMatches ? rowMatches.length : 0;
84
- // Description: schema may carry an `engineering-type` description.
85
107
  const descMatch = /<engineering-description>([^<]+)<\/engineering-description>/.exec(body);
86
108
  const description = descMatch?.[1]?.trim();
87
109
  schemas.push({
@@ -90,15 +112,36 @@ export function parseTraceToc(xml, tracePath) {
90
112
  ...(description ? { description } : {}),
91
113
  });
92
114
  }
115
+ // Self-closing form: `<table schema="X" .../>`. Skip ranges already
116
+ // matched by openCloseRegex so we don't double-count when a body contains
117
+ // nested self-closing tables (unlikely but defensive).
118
+ const selfCloseRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*\/>/g;
119
+ while ((match = selfCloseRegex.exec(xml)) !== null) {
120
+ const start = match.index;
121
+ if (seenRanges.some(([s, e]) => start >= s && start < e))
122
+ continue;
123
+ const name = match[1];
124
+ schemas.push({
125
+ name,
126
+ rowCount: 0, // TOC self-closing tables carry no rows; rowCount must be filled by the async row-counting step in inspectTrace().
127
+ });
128
+ }
93
129
  schemas.sort((a, b) => b.rowCount - a.rowCount);
94
130
  const rowCounts = {};
95
131
  for (const s of schemas)
96
132
  rowCounts[s.name] = s.rowCount;
97
133
  // Run-level metadata extracted from the TOC's <run> attributes / children.
98
- const deviceMatch = /<device-model>([^<]+)<\/device-model>/.exec(xml);
99
- const osMatch = /<os-version>([^<]+)<\/os-version>/.exec(xml);
134
+ // Apple's --toc output exposes device + OS as ATTRIBUTES on <device .../>
135
+ // and uses <start-date> instead of <recorded-when>. We try the Apple
136
+ // attribute form first, fall back to legacy text-element form for
137
+ // synthetic fixtures.
138
+ const deviceAttrMatch = /<device\b[^>]*\bmodel="([^"]+)"/.exec(xml);
139
+ const deviceMatch = deviceAttrMatch ?? /<device-model>([^<]+)<\/device-model>/.exec(xml);
140
+ const osAttrMatch = /<device\b[^>]*\bos-version="([^"]+)"/.exec(xml);
141
+ const osMatch = osAttrMatch ?? /<os-version>([^<]+)<\/os-version>/.exec(xml);
100
142
  const templateMatch = /<template-name>([^<]+)<\/template-name>/.exec(xml);
101
- const recordedMatch = /<recorded-when>([^<]+)<\/recorded-when>/.exec(xml);
143
+ const recordedAttrMatch = /<start-date>([^<]+)<\/start-date>/.exec(xml);
144
+ const recordedMatch = recordedAttrMatch ?? /<recorded-when>([^<]+)<\/recorded-when>/.exec(xml);
102
145
  const suggestedNextCalls = [];
103
146
  for (const s of schemas) {
104
147
  if (s.rowCount === 0)
@@ -142,6 +185,36 @@ function buildDiagnosis(schemas, templateName) {
142
185
  }
143
186
  return parts.join(" ");
144
187
  }
188
+ /**
189
+ * Count `<row>` elements for a single schema by running a targeted xpath
190
+ * query. Used by `inspectTrace` to fill in row counts that the bare
191
+ * `--toc` output omits (Apple's TOC emits self-closing `<table/>` elements
192
+ * with column metadata only, no rows).
193
+ *
194
+ * Bounded by a 60s xctrace timeout each. On any failure we treat as zero
195
+ * rows rather than throwing: an empty result is the same semantic outcome
196
+ * as a missing schema, and downstream `summarizeTrace` already handles
197
+ * `rowCount === 0` as "schema-absent".
198
+ */
199
+ async function countSchemaRows(tracePath, schemaName) {
200
+ try {
201
+ const result = await runCommand("xcrun", [
202
+ "xctrace",
203
+ "export",
204
+ "--input",
205
+ tracePath,
206
+ "--xpath",
207
+ `/trace-toc/run/data/table[@schema="${schemaName}"]`,
208
+ ], { timeoutMs: 60_000 });
209
+ if (result.code !== 0)
210
+ return 0;
211
+ const rowMatches = result.stdout.match(/<row\b/g);
212
+ return rowMatches ? rowMatches.length : 0;
213
+ }
214
+ catch {
215
+ return 0;
216
+ }
217
+ }
145
218
  export async function inspectTrace(input) {
146
219
  const tracePath = resolvePath(input.tracePath);
147
220
  if (!existsSync(tracePath)) {
@@ -155,22 +228,55 @@ export async function inspectTrace(input) {
155
228
  // The bundle is a directory on macOS; stat reports the directory inode
156
229
  // size, which is fine for orientation. Failures are non-fatal.
157
230
  }
158
- const result = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--xpath", "/trace-toc/run"], { timeoutMs: 60_000 });
231
+ // Apple's `xctrace export --toc` is the canonical schema-discovery surface.
232
+ // The previously-used `--xpath '/trace-toc/run'` returns "no content to
233
+ // export" against real Apple-produced .trace bundles (validated 2026-05-15
234
+ // against wishlist-tti-device.trace). The --toc flag returns the full
235
+ // table-of-contents XML including all `<table schema="..."/>` elements.
236
+ const result = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--toc"], { timeoutMs: 60_000 });
159
237
  if (result.code !== 0) {
160
- // Fallback: when the targeted xpath fails (older xctrace versions, or
161
- // a trace with no /run node), try the broader /trace-toc xpath and
162
- // parse whatever schemas surface.
163
- const fallback = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--xpath", "/trace-toc"], { timeoutMs: 60_000 });
164
- if (fallback.code !== 0) {
165
- throw new Error(`xctrace export TOC failed (code ${result.code}): ${result.stderr || result.stdout || "<no output>"}`);
166
- }
167
- const parsed = parseTraceToc(fallback.stdout, tracePath);
168
- return { ok: true, ...parsed, ...(fileSize != null ? { fileSize } : {}) };
238
+ throw new Error(`xctrace export --toc failed (code ${result.code}): ${result.stderr || result.stdout || "<no output>"}`);
169
239
  }
170
240
  const parsed = parseTraceToc(result.stdout, tracePath);
241
+ // The TOC carries schema NAMES + column metadata but no rows. Fill in
242
+ // row counts for the schemas an analyzer can consume (the ones in
243
+ // SCHEMA_TO_ANALYZER) so `summarizeTrace` can decide which analyzers to
244
+ // run. Other schemas (tick, kdebug, life-cycle-period, etc.) are left at
245
+ // rowCount=0; nothing downstream consumes them.
246
+ const knownSchemas = Object.keys(SCHEMA_TO_ANALYZER);
247
+ const schemasInTrace = new Set(parsed.schemas.map((s) => s.name));
248
+ const schemasToCount = knownSchemas.filter((name) => schemasInTrace.has(name));
249
+ const counts = await Promise.all(schemasToCount.map(async (name) => [name, await countSchemaRows(tracePath, name)]));
250
+ const rowCounts = { ...parsed.rowCounts };
251
+ for (const [name, count] of counts)
252
+ rowCounts[name] = count;
253
+ const updatedSchemas = parsed.schemas.map((s) => rowCounts[s.name] != null && rowCounts[s.name] !== s.rowCount
254
+ ? { ...s, rowCount: rowCounts[s.name] }
255
+ : s);
256
+ updatedSchemas.sort((a, b) => b.rowCount - a.rowCount);
257
+ // Recompute suggestedNextCalls now that row counts are accurate.
258
+ const suggestedNextCalls = [];
259
+ for (const s of updatedSchemas) {
260
+ if (s.rowCount === 0)
261
+ continue;
262
+ const mapping = SCHEMA_TO_ANALYZER[s.name];
263
+ if (!mapping)
264
+ continue;
265
+ suggestedNextCalls.push({
266
+ tool: mapping.tool,
267
+ args: { tracePath },
268
+ why: `${s.rowCount.toLocaleString()} rows in the ${s.name} schema. ${mapping.description}`,
269
+ });
270
+ }
271
+ // Recompute diagnosis with accurate row counts.
272
+ const diagnosis = buildDiagnosis(updatedSchemas, parsed.templateName);
171
273
  return {
172
274
  ok: true,
173
275
  ...parsed,
276
+ schemas: updatedSchemas,
277
+ rowCounts,
278
+ suggestedNextCalls,
279
+ diagnosis,
174
280
  ...(fileSize != null ? { fileSize } : {}),
175
281
  };
176
282
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inspectTrace.js","sourceRoot":"","sources":["../../src/tools/inspectTrace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inspectTrace.js","sourceRoot":"","sources":["../../src/tools/inspectTrace.ts"],"names":[],"mappings":"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"}
@@ -87,7 +87,90 @@ export interface RecordTimeProfileResult {
87
87
  * and the practical mitigations.
88
88
  */
89
89
  workaroundNotice?: RecordingTimeoutWorkaroundNotice;
90
+ /**
91
+ * v1.14+. `true` when, after a timed-out recording, the wrapper invoked
92
+ * `open -a Instruments <tracePath>` so the user can inspect the partial
93
+ * trace in the GUI (Instruments.app on macOS 26.x can still open and
94
+ * symbolicate traces the CLI export path rejects). Opt-in via
95
+ * `MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS=1`. `false` when the env flag is
96
+ * unset (default) or the trace bundle is missing from disk. Absent when
97
+ * the recording did not time out.
98
+ */
99
+ openedInInstrumentsApp?: boolean;
100
+ }
101
+ /**
102
+ * v1.14 item H. Pre-flight probe for the xctrace `--time-limit` ignore
103
+ * regression on macOS 26.x simulators. Runs a 2-second test recording
104
+ * against the same target the user requested. If the probe completes
105
+ * cleanly inside its wrapper window, the user's full recording is
106
+ * expected to behave; if the probe times out, we bail before spending
107
+ * the user's full `durationSec` + 30s grace window on a wedge.
108
+ *
109
+ * Returns `{ healthy: true }` when the probe exited cleanly. Returns
110
+ * `{ healthy: false, reason }` when the probe timed out OR when xctrace
111
+ * exited non-zero (the wedge does not always produce timedOut=true;
112
+ * sometimes xctrace exits early with a misleading error code when the
113
+ * sim is in a bad state). The recordTimeProfile flow treats either as
114
+ * "skip the full recording, return workaroundNotice now".
115
+ *
116
+ * Pre-flight is gated to ATTACH mode only. The `--launch` path would
117
+ * start the user's app a second time (probe launch + full-recording
118
+ * launch), losing first-launch state. For `--launch` callers we skip
119
+ * the probe and fall back to the existing 70s timeout wrapper.
120
+ *
121
+ * Exported so the gating logic can be unit-tested without spawning
122
+ * xctrace.
123
+ */
124
+ export interface PreflightResult {
125
+ healthy: boolean;
126
+ reason?: string;
127
+ durationMs: number;
90
128
  }
129
+ /**
130
+ * Returns true when a pre-flight probe should run before the user's
131
+ * actual recording. v1.14 item H.
132
+ *
133
+ * - `MEMORYDETECTIVE_PREFLIGHT_XCTRACE=1` forces preflight on.
134
+ * - `MEMORYDETECTIVE_PREFLIGHT_XCTRACE=0` forces it off.
135
+ * - Default: auto-enabled when host is macOS 26.x AND target is a
136
+ * simulator AND attach mode (`--attach`, not `--launch`). The set of
137
+ * configurations where the regression is known to fire.
138
+ *
139
+ * The `osPlatform` and `osRelease` params are threaded through to
140
+ * `getPlatformAdvisory` so tests can simulate non-macOS-26 hosts even
141
+ * when running on a real macOS 26.x machine.
142
+ */
143
+ export declare function shouldPreflightXctrace(input: RecordTimeProfileInput, env?: Readonly<Record<string, string | undefined>>, osPlatform?: () => NodeJS.Platform, osRelease?: () => string): boolean;
144
+ /**
145
+ * Runs the 2-second probe. Reuses runCommand's timeout wrapper with the
146
+ * same SIGINT-first / SIGKILL-fallback shape that the full recording
147
+ * uses, so the probe's salvage behavior matches the real path.
148
+ *
149
+ * The output bundle is placed at `<output>.preflight` to keep it
150
+ * recognizable in cleanup tools and not collide with the user's actual
151
+ * output path.
152
+ */
153
+ export declare function preflightXctraceRecord(input: RecordTimeProfileInput, resolvedOutput: string): Promise<PreflightResult>;
154
+ /**
155
+ * v1.14 item J. When a `recordTimeProfile` call times out, optionally
156
+ * launch the partial `.trace` in Instruments.app so the user has a GUI
157
+ * escape hatch. Returns `true` when `open -a Instruments <tracePath>`
158
+ * was spawned, `false` otherwise.
159
+ *
160
+ * Gated on `MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS=1` to avoid spamming
161
+ * the user's GUI on unattended runs and CI. Also requires the trace
162
+ * bundle to exist on disk (xctrace's SIGINT path may have failed to
163
+ * write anything).
164
+ *
165
+ * The `open` invocation is fire-and-forget: `detached: true` + `unref()`
166
+ * so the recording tool returns immediately. Failures to launch
167
+ * Instruments.app are swallowed; the user is no worse off than without
168
+ * the flag enabled.
169
+ *
170
+ * Exported so the env-gating logic can be tested without spawning
171
+ * Instruments in test runs.
172
+ */
173
+ export declare function maybeOpenInInstruments(tracePath: string): boolean;
91
174
  /** Pure: build the xctrace argv for the given input. Exposed for testing. */
92
175
  export declare function buildXctraceArgs(input: RecordTimeProfileInput): string[];
93
176
  export declare function recordTimeProfile(input: RecordTimeProfileInput): Promise<RecordTimeProfileResult>;