@xctrace-analyzer/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,306 @@
1
+ /**
2
+ * RecommendationEngine - Generates actionable optimization recommendations
3
+ */
4
+ const RECOMMENDATION_RULES = [
5
+ // Image processing
6
+ {
7
+ pattern: /image|bitmap|cgimage|uiimage|resize|scale/i,
8
+ type: 'caching',
9
+ priority: 'high',
10
+ title: 'Implement Image Caching',
11
+ descriptionTemplate: 'Frequent image operations detected. Consider implementing NSCache or disk-based caching to avoid repeated processing.',
12
+ potentialImprovement: '50-70% reduction in image processing time',
13
+ codeExample: `let imageCache = NSCache<NSString, UIImage>()
14
+
15
+ func cachedImage(for key: String) -> UIImage? {
16
+ if let cached = imageCache.object(forKey: key as NSString) {
17
+ return cached
18
+ }
19
+ let image = processImage(key)
20
+ imageCache.setObject(image, forKey: key as NSString)
21
+ return image
22
+ }`,
23
+ },
24
+ // JSON parsing
25
+ {
26
+ pattern: /json|parse|decode|jsonSerialization/i,
27
+ type: 'async',
28
+ priority: 'high',
29
+ title: 'Move JSON Parsing to Background Thread',
30
+ descriptionTemplate: 'JSON parsing is blocking the main thread. Consider using async/await or background queues for parsing.',
31
+ potentialImprovement: 'Improved UI responsiveness',
32
+ codeExample: `Task {
33
+ let data = await fetchData()
34
+ let decoded = try JSONDecoder().decode(Model.self, from: data)
35
+ await MainActor.run {
36
+ updateUI(with: decoded)
37
+ }
38
+ }`,
39
+ },
40
+ // Database operations
41
+ {
42
+ pattern: /database|sql|query|fetch|coredata|realm/i,
43
+ type: 'optimization',
44
+ priority: 'high',
45
+ title: 'Optimize Database Queries',
46
+ descriptionTemplate: 'Database operations are taking significant time. Consider adding indexes, batching queries, or using query optimization techniques.',
47
+ potentialImprovement: '40-60% faster queries',
48
+ codeExample: `// Add index
49
+ entity.index(on: \\.propertyName)
50
+
51
+ // Batch fetching
52
+ let request = NSFetchRequest<Entity>(entityName: "Entity")
53
+ request.fetchBatchSize = 20`,
54
+ },
55
+ // Network operations
56
+ {
57
+ pattern: /network|http|request|url|download|upload/i,
58
+ type: 'caching',
59
+ priority: 'medium',
60
+ title: 'Implement Response Caching',
61
+ descriptionTemplate: 'Frequent network requests detected. Consider implementing request caching or batching multiple requests.',
62
+ potentialImprovement: 'Reduced network calls and faster response times',
63
+ },
64
+ // Sorting/filtering
65
+ {
66
+ pattern: /sort|filter|search|find/i,
67
+ type: 'algorithm',
68
+ priority: 'medium',
69
+ title: 'Optimize Collection Operations',
70
+ descriptionTemplate: 'Frequent collection operations detected. Consider using more efficient algorithms or pre-computed indexes.',
71
+ potentialImprovement: '30-50% faster operations',
72
+ codeExample: `// Use Set for O(1) lookups instead of Array.contains
73
+ let idSet = Set(ids)
74
+ let filtered = items.filter { idSet.contains($0.id) }`,
75
+ },
76
+ // View layout
77
+ {
78
+ pattern: /layout|constraint|autolayout|updateConstraints|layoutSubviews/i,
79
+ type: 'optimization',
80
+ priority: 'medium',
81
+ title: 'Simplify View Hierarchy',
82
+ descriptionTemplate: 'Auto Layout is consuming significant time. Consider simplifying view hierarchy or using manual layout for performance-critical views.',
83
+ potentialImprovement: 'Faster view updates and animations',
84
+ },
85
+ // Cryptography
86
+ {
87
+ pattern: /crypto|encrypt|decrypt|hash|hmac|aes/i,
88
+ type: 'async',
89
+ priority: 'high',
90
+ title: 'Move Cryptographic Operations Off Main Thread',
91
+ descriptionTemplate: 'Cryptographic operations are blocking. These should always run on background threads.',
92
+ potentialImprovement: 'Improved UI responsiveness',
93
+ },
94
+ // File I/O
95
+ {
96
+ pattern: /file|read|write|fileManager|document/i,
97
+ type: 'async',
98
+ priority: 'high',
99
+ title: 'Perform File I/O Asynchronously',
100
+ descriptionTemplate: 'File operations are blocking the main thread. Use async I/O or background queues.',
101
+ potentialImprovement: 'Non-blocking I/O operations',
102
+ },
103
+ ];
104
+ /**
105
+ * Generates optimization recommendations from analysis
106
+ */
107
+ export class RecommendationEngine {
108
+ /**
109
+ * Generate recommendations for an analysis
110
+ */
111
+ generateRecommendations(analysis) {
112
+ const recommendations = [];
113
+ // Generate recommendations from bottlenecks
114
+ for (const bottleneck of analysis.bottlenecks) {
115
+ const recommendation = this.generateRecommendationForBottleneck(bottleneck);
116
+ if (recommendation) {
117
+ recommendations.push(recommendation);
118
+ }
119
+ }
120
+ // Add general recommendations based on stats
121
+ recommendations.push(...this.generateGeneralRecommendations(analysis));
122
+ recommendations.push(...this.generateInstrumentRecommendations(analysis));
123
+ // Remove duplicates and prioritize
124
+ return this.deduplicateAndPrioritize(recommendations);
125
+ }
126
+ /**
127
+ * Generate recommendation for a specific bottleneck
128
+ */
129
+ generateRecommendationForBottleneck(bottleneck) {
130
+ const functionName = `${bottleneck.module || ''}${bottleneck.function}`;
131
+ // Try to match against patterns
132
+ for (const rule of RECOMMENDATION_RULES) {
133
+ if (rule.pattern.test(functionName)) {
134
+ return {
135
+ type: rule.type,
136
+ priority: this.adjustPriority(rule.priority, bottleneck.impact),
137
+ title: rule.title,
138
+ description: rule.descriptionTemplate,
139
+ affectedFunctions: [bottleneck.function],
140
+ potentialImprovement: rule.potentialImprovement || `~${bottleneck.duration.toFixed(0)}ms`,
141
+ codeExample: rule.codeExample,
142
+ };
143
+ }
144
+ }
145
+ // Generic recommendation if no pattern matches
146
+ if (bottleneck.impact === 'critical' || bottleneck.impact === 'high') {
147
+ return {
148
+ type: 'optimization',
149
+ priority: bottleneck.impact === 'critical' ? 'high' : 'medium',
150
+ title: `Optimize ${bottleneck.function}`,
151
+ description: bottleneck.suggestion,
152
+ affectedFunctions: [bottleneck.function],
153
+ potentialImprovement: `~${bottleneck.duration.toFixed(0)}ms (${bottleneck.percentage.toFixed(1)}% of total time)`,
154
+ };
155
+ }
156
+ return null;
157
+ }
158
+ /**
159
+ * Generate general recommendations based on overall stats
160
+ */
161
+ generateGeneralRecommendations(analysis) {
162
+ const recommendations = [];
163
+ // Too many slow functions
164
+ if (analysis.stats.slowFunctions > 10) {
165
+ recommendations.push({
166
+ type: 'architecture',
167
+ priority: 'medium',
168
+ title: 'Consider Architectural Refactoring',
169
+ description: `Found ${analysis.stats.slowFunctions} slow functions. This suggests the need for broader architectural improvements rather than individual function optimizations.`,
170
+ affectedFunctions: [],
171
+ potentialImprovement: 'Overall better performance and maintainability',
172
+ });
173
+ }
174
+ // High thread contention (many threads but poor performance)
175
+ if (analysis.stats.threadCount > 8 && analysis.stats.avgFunctionTime > 100) {
176
+ recommendations.push({
177
+ type: 'architecture',
178
+ priority: 'medium',
179
+ title: 'Review Thread Management',
180
+ description: `High thread count (${analysis.stats.threadCount}) but slow performance suggests thread contention or over-parallelization. Consider reducing concurrent operations.`,
181
+ affectedFunctions: [],
182
+ potentialImprovement: 'Reduced thread contention and context switching',
183
+ });
184
+ }
185
+ return recommendations;
186
+ }
187
+ /**
188
+ * Generate recommendations from non-Time-Profiler instrument findings.
189
+ */
190
+ generateInstrumentRecommendations(analysis) {
191
+ const recommendations = [];
192
+ for (const instrument of analysis.instrumentAnalyses ?? []) {
193
+ for (const finding of instrument.findings) {
194
+ switch (instrument.kind) {
195
+ case 'memory':
196
+ recommendations.push({
197
+ type: 'memory',
198
+ priority: this.priorityFromFinding(finding.severity),
199
+ title: 'Investigate Memory Usage',
200
+ description: finding.description,
201
+ affectedFunctions: [],
202
+ potentialImprovement: 'Lower peak memory and fewer memory pressure events',
203
+ });
204
+ break;
205
+ case 'allocations':
206
+ recommendations.push({
207
+ type: 'memory',
208
+ priority: this.priorityFromFinding(finding.severity),
209
+ title: 'Reduce Allocation Churn',
210
+ description: finding.description,
211
+ affectedFunctions: [],
212
+ potentialImprovement: 'Fewer allocations and less allocator overhead',
213
+ });
214
+ break;
215
+ case 'leaks':
216
+ recommendations.push({
217
+ type: 'memory',
218
+ priority: this.priorityFromFinding(finding.severity),
219
+ title: 'Investigate Memory Leaks',
220
+ description: finding.description,
221
+ affectedFunctions: [],
222
+ potentialImprovement: 'Recovered leaked memory and improved long-session stability',
223
+ });
224
+ break;
225
+ case 'network':
226
+ recommendations.push({
227
+ type: 'caching',
228
+ priority: this.priorityFromFinding(finding.severity),
229
+ title: 'Review Network Reliability',
230
+ description: finding.description,
231
+ affectedFunctions: [],
232
+ potentialImprovement: 'Fewer failed requests and less redundant transfer',
233
+ });
234
+ break;
235
+ case 'energy':
236
+ recommendations.push({
237
+ type: 'optimization',
238
+ priority: this.priorityFromFinding(finding.severity),
239
+ title: 'Reduce Energy Impact',
240
+ description: finding.description,
241
+ affectedFunctions: [],
242
+ potentialImprovement: 'Lower battery usage and less background activity',
243
+ });
244
+ break;
245
+ }
246
+ }
247
+ }
248
+ return recommendations;
249
+ }
250
+ priorityFromFinding(severity) {
251
+ if (severity === 'critical' || severity === 'high') {
252
+ return 'high';
253
+ }
254
+ if (severity === 'medium') {
255
+ return 'medium';
256
+ }
257
+ return 'low';
258
+ }
259
+ /**
260
+ * Adjust priority based on bottleneck impact
261
+ */
262
+ adjustPriority(basePriority, impact) {
263
+ if (impact === 'critical') {
264
+ return 'high';
265
+ }
266
+ if (impact === 'high' && basePriority === 'medium') {
267
+ return 'high';
268
+ }
269
+ if (impact === 'low' && basePriority === 'high') {
270
+ return 'medium';
271
+ }
272
+ return basePriority;
273
+ }
274
+ /**
275
+ * Remove duplicate recommendations and prioritize
276
+ */
277
+ deduplicateAndPrioritize(recommendations) {
278
+ // Use title as deduplication key
279
+ const seen = new Map();
280
+ for (const rec of recommendations) {
281
+ const existing = seen.get(rec.title);
282
+ if (!existing) {
283
+ seen.set(rec.title, rec);
284
+ }
285
+ else {
286
+ // Merge affected functions
287
+ const combined = {
288
+ ...existing,
289
+ affectedFunctions: [...new Set([...existing.affectedFunctions, ...rec.affectedFunctions])],
290
+ };
291
+ seen.set(rec.title, combined);
292
+ }
293
+ }
294
+ // Sort by priority
295
+ const priorityOrder = { high: 0, medium: 1, low: 2 };
296
+ return Array.from(seen.values()).sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
297
+ }
298
+ }
299
+ /**
300
+ * Convenience function to generate recommendations
301
+ */
302
+ export function generateRecommendations(analysis) {
303
+ const engine = new RecommendationEngine();
304
+ return engine.generateRecommendations(analysis);
305
+ }
306
+ //# sourceMappingURL=recommendation-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommendation-engine.js","sourceRoot":"","sources":["../../src/analyzer/recommendation-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH,MAAM,oBAAoB,GAAyB;IACjD,mBAAmB;IACnB;QACE,OAAO,EAAE,4CAA4C;QACrD,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,yBAAyB;QAChC,mBAAmB,EAAE,uHAAuH;QAC5I,oBAAoB,EAAE,2CAA2C;QACjE,WAAW,EAAE;;;;;;;;;EASf;KACC;IAED,eAAe;IACf;QACE,OAAO,EAAE,sCAAsC;QAC/C,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,wCAAwC;QAC/C,mBAAmB,EAAE,wGAAwG;QAC7H,oBAAoB,EAAE,4BAA4B;QAClD,WAAW,EAAE;;;;;;EAMf;KACC;IAED,sBAAsB;IACtB;QACE,OAAO,EAAE,0CAA0C;QACnD,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,2BAA2B;QAClC,mBAAmB,EAAE,qIAAqI;QAC1J,oBAAoB,EAAE,uBAAuB;QAC7C,WAAW,EAAE;;;;;4BAKW;KACzB;IAED,qBAAqB;IACrB;QACE,OAAO,EAAE,2CAA2C;QACpD,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,4BAA4B;QACnC,mBAAmB,EAAE,0GAA0G;QAC/H,oBAAoB,EAAE,iDAAiD;KACxE;IAED,oBAAoB;IACpB;QACE,OAAO,EAAE,0BAA0B;QACnC,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,gCAAgC;QACvC,mBAAmB,EAAE,4GAA4G;QACjI,oBAAoB,EAAE,0BAA0B;QAChD,WAAW,EAAE;;sDAEqC;KACnD;IAED,cAAc;IACd;QACE,OAAO,EAAE,gEAAgE;QACzE,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,yBAAyB;QAChC,mBAAmB,EAAE,uIAAuI;QAC5J,oBAAoB,EAAE,oCAAoC;KAC3D;IAED,eAAe;IACf;QACE,OAAO,EAAE,uCAAuC;QAChD,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,+CAA+C;QACtD,mBAAmB,EAAE,uFAAuF;QAC5G,oBAAoB,EAAE,4BAA4B;KACnD;IAED,WAAW;IACX;QACE,OAAO,EAAE,uCAAuC;QAChD,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,iCAAiC;QACxC,mBAAmB,EAAE,mFAAmF;QACxG,oBAAoB,EAAE,6BAA6B;KACpD;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAC/B;;OAEG;IACH,uBAAuB,CAAC,QAAkB;QACxC,MAAM,eAAe,GAAqB,EAAE,CAAC;QAE7C,4CAA4C;QAC5C,KAAK,MAAM,UAAU,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,mCAAmC,CAAC,UAAU,CAAC,CAAC;YAC5E,IAAI,cAAc,EAAE,CAAC;gBACnB,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,8BAA8B,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvE,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,iCAAiC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE1E,mCAAmC;QACnC,OAAO,IAAI,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACK,mCAAmC,CAAC,UAAsB;QAChE,MAAM,YAAY,GAAG,GAAG,UAAU,CAAC,MAAM,IAAI,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,CAAC;QAExE,gCAAgC;QAChC,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBACpC,OAAO;oBACL,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC;oBAC/D,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,WAAW,EAAE,IAAI,CAAC,mBAAmB;oBACrC,iBAAiB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;oBACxC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;oBACzF,WAAW,EAAE,IAAI,CAAC,WAAW;iBAC9B,CAAC;YACJ,CAAC;QACH,CAAC;QAED,+CAA+C;QAC/C,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACrE,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,QAAQ,EAAE,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;gBAC9D,KAAK,EAAE,YAAY,UAAU,CAAC,QAAQ,EAAE;gBACxC,WAAW,EAAE,UAAU,CAAC,UAAU;gBAClC,iBAAiB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;gBACxC,oBAAoB,EAAE,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB;aAClH,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACK,8BAA8B,CAAC,QAAkB;QACvD,MAAM,eAAe,GAAqB,EAAE,CAAC;QAE7C,0BAA0B;QAC1B,IAAI,QAAQ,CAAC,KAAK,CAAC,aAAa,GAAG,EAAE,EAAE,CAAC;YACtC,eAAe,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,cAAc;gBACpB,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,oCAAoC;gBAC3C,WAAW,EAAE,SAAS,QAAQ,CAAC,KAAK,CAAC,aAAa,+HAA+H;gBACjL,iBAAiB,EAAE,EAAE;gBACrB,oBAAoB,EAAE,gDAAgD;aACvE,CAAC,CAAC;QACL,CAAC;QAED,6DAA6D;QAC7D,IAAI,QAAQ,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,eAAe,GAAG,GAAG,EAAE,CAAC;YAC3E,eAAe,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,cAAc;gBACpB,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,0BAA0B;gBACjC,WAAW,EAAE,sBAAsB,QAAQ,CAAC,KAAK,CAAC,WAAW,qHAAqH;gBAClL,iBAAiB,EAAE,EAAE;gBACrB,oBAAoB,EAAE,iDAAiD;aACxE,CAAC,CAAC;QACL,CAAC;QAED,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;OAEG;IACK,iCAAiC,CAAC,QAAkB;QAC1D,MAAM,eAAe,GAAqB,EAAE,CAAC;QAE7C,KAAK,MAAM,UAAU,IAAI,QAAQ,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC;YAC3D,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;gBAC1C,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;oBACxB,KAAK,QAAQ;wBACX,eAAe,CAAC,IAAI,CAAC;4BACnB,IAAI,EAAE,QAAQ;4BACd,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;4BACpD,KAAK,EAAE,0BAA0B;4BACjC,WAAW,EAAE,OAAO,CAAC,WAAW;4BAChC,iBAAiB,EAAE,EAAE;4BACrB,oBAAoB,EAAE,oDAAoD;yBAC3E,CAAC,CAAC;wBACH,MAAM;oBACR,KAAK,aAAa;wBAChB,eAAe,CAAC,IAAI,CAAC;4BACnB,IAAI,EAAE,QAAQ;4BACd,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;4BACpD,KAAK,EAAE,yBAAyB;4BAChC,WAAW,EAAE,OAAO,CAAC,WAAW;4BAChC,iBAAiB,EAAE,EAAE;4BACrB,oBAAoB,EAAE,+CAA+C;yBACtE,CAAC,CAAC;wBACH,MAAM;oBACR,KAAK,OAAO;wBACV,eAAe,CAAC,IAAI,CAAC;4BACnB,IAAI,EAAE,QAAQ;4BACd,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;4BACpD,KAAK,EAAE,0BAA0B;4BACjC,WAAW,EAAE,OAAO,CAAC,WAAW;4BAChC,iBAAiB,EAAE,EAAE;4BACrB,oBAAoB,EAAE,6DAA6D;yBACpF,CAAC,CAAC;wBACH,MAAM;oBACR,KAAK,SAAS;wBACZ,eAAe,CAAC,IAAI,CAAC;4BACnB,IAAI,EAAE,SAAS;4BACf,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;4BACpD,KAAK,EAAE,4BAA4B;4BACnC,WAAW,EAAE,OAAO,CAAC,WAAW;4BAChC,iBAAiB,EAAE,EAAE;4BACrB,oBAAoB,EAAE,mDAAmD;yBAC1E,CAAC,CAAC;wBACH,MAAM;oBACR,KAAK,QAAQ;wBACX,eAAe,CAAC,IAAI,CAAC;4BACnB,IAAI,EAAE,cAAc;4BACpB,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;4BACpD,KAAK,EAAE,sBAAsB;4BAC7B,WAAW,EAAE,OAAO,CAAC,WAAW;4BAChC,iBAAiB,EAAE,EAAE;4BACrB,oBAAoB,EAAE,kDAAkD;yBACzE,CAAC,CAAC;wBACH,MAAM;gBACV,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,eAAe,CAAC;IACzB,CAAC;IAEO,mBAAmB,CAAC,QAAyD;QACnF,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACnD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACK,cAAc,CACpB,YAAwC,EACxC,MAA4B;QAE5B,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1B,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,MAAM,KAAK,MAAM,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YACnD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,MAAM,KAAK,KAAK,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAChD,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,wBAAwB,CAAC,eAAiC;QAChE,iCAAiC;QACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAA0B,CAAC;QAE/C,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,2BAA2B;gBAC3B,MAAM,QAAQ,GAAG;oBACf,GAAG,QAAQ;oBACX,iBAAiB,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,iBAAiB,EAAE,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;iBAC3F,CAAC;gBACF,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,MAAM,aAAa,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACrD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAChE,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAkB;IACxD,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC1C,OAAO,MAAM,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @xctrace-analyzer/core
3
+ *
4
+ * Core analysis library for Xcode Instruments traces
5
+ */
6
+ export * from './types.js';
7
+ export { TraceParser, parseTrace, type TraceExporter, type TraceParserOptions } from './parser/trace-parser.js';
8
+ export { PerformanceAnalyzer, analyzeTrace } from './analyzer/performance-analyzer.js';
9
+ export { ComparativeAnalyzer, compareTraces } from './analyzer/comparative-analyzer.js';
10
+ export { RecommendationEngine, generateRecommendations } from './analyzer/recommendation-engine.js';
11
+ export * from './utils/xctrace-runner.js';
12
+ import { Analysis, AnalysisOptions } from './types.js';
13
+ export declare function analyzeTraceFile(tracePath: string, options?: AnalysisOptions): Promise<Analysis>;
14
+ import { Comparison, ComparisonOptions } from './types.js';
15
+ export declare function compareTraceFiles(baselinePath: string, currentPath: string, analysisOptions?: AnalysisOptions, comparisonOptions?: ComparisonOptions): Promise<Comparison>;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGhH,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAGpG,cAAc,2BAA2B,CAAC;AAQ1C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,QAAQ,CAAC,CAgBnB;AAMD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE3D,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,eAAe,EACjC,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,UAAU,CAAC,CASrB"}
package/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @xctrace-analyzer/core
3
+ *
4
+ * Core analysis library for Xcode Instruments traces
5
+ */
6
+ // Export types
7
+ export * from './types.js';
8
+ // Export parser
9
+ export { TraceParser, parseTrace } from './parser/trace-parser.js';
10
+ // Export analyzers
11
+ export { PerformanceAnalyzer, analyzeTrace } from './analyzer/performance-analyzer.js';
12
+ export { ComparativeAnalyzer, compareTraces } from './analyzer/comparative-analyzer.js';
13
+ export { RecommendationEngine, generateRecommendations } from './analyzer/recommendation-engine.js';
14
+ // Export utilities
15
+ export * from './utils/xctrace-runner.js';
16
+ /**
17
+ * High-level convenience function: parse and analyze a trace in one call
18
+ */
19
+ import { parseTrace } from './parser/trace-parser.js';
20
+ import { analyzeTrace } from './analyzer/performance-analyzer.js';
21
+ import { generateRecommendations } from './analyzer/recommendation-engine.js';
22
+ export async function analyzeTraceFile(tracePath, options) {
23
+ // Parse the trace
24
+ const parsed = await parseTrace(tracePath, options?.timeRangeMs ? { timeRangeMs: options.timeRangeMs } : undefined);
25
+ // Analyze it
26
+ const analysis = analyzeTrace(parsed, options);
27
+ // Add recommendations
28
+ if (options?.includeRecommendations !== false) {
29
+ analysis.recommendations = generateRecommendations(analysis);
30
+ }
31
+ return analysis;
32
+ }
33
+ /**
34
+ * High-level convenience function: compare two traces
35
+ */
36
+ import { compareTraces } from './analyzer/comparative-analyzer.js';
37
+ export async function compareTraceFiles(baselinePath, currentPath, analysisOptions, comparisonOptions) {
38
+ // Parse and analyze both traces
39
+ const [baselineAnalysis, currentAnalysis] = await Promise.all([
40
+ analyzeTraceFile(baselinePath, analysisOptions),
41
+ analyzeTraceFile(currentPath, analysisOptions),
42
+ ]);
43
+ // Compare them
44
+ return compareTraces(baselineAnalysis, currentAnalysis, comparisonOptions);
45
+ }
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,cAAc,YAAY,CAAC;AAE3B,gBAAgB;AAChB,OAAO,EAAE,WAAW,EAAE,UAAU,EAA+C,MAAM,0BAA0B,CAAC;AAEhH,mBAAmB;AACnB,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAEpG,mBAAmB;AACnB,cAAc,2BAA2B,CAAC;AAE1C;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAG9E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,OAAyB;IAEzB,kBAAkB;IAClB,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,SAAS,EACT,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CACxE,CAAC;IAEF,aAAa;IACb,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/C,sBAAsB;IACtB,IAAI,OAAO,EAAE,sBAAsB,KAAK,KAAK,EAAE,CAAC;QAC9C,QAAQ,CAAC,eAAe,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGnE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,YAAoB,EACpB,WAAmB,EACnB,eAAiC,EACjC,iBAAqC;IAErC,gCAAgC;IAChC,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC5D,gBAAgB,CAAC,YAAY,EAAE,eAAe,CAAC;QAC/C,gBAAgB,CAAC,WAAW,EAAE,eAAe,CAAC;KAC/C,CAAC,CAAC;IAEH,eAAe;IACf,OAAO,aAAa,CAAC,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * TraceParser - Parses Xcode Instruments trace files
3
+ */
4
+ import { ParsedTrace, TimeRangeMs } from '../types.js';
5
+ export interface TraceExporter {
6
+ exportTOC(tracePath: string): Promise<string>;
7
+ exportTable(tracePath: string, schema: string, runNumber?: number): Promise<string>;
8
+ exportXPath?(tracePath: string, xpath: string): Promise<string>;
9
+ exportHAR?(tracePath: string): Promise<string>;
10
+ }
11
+ export interface TraceParserOptions {
12
+ timeRangeMs?: TimeRangeMs;
13
+ }
14
+ /**
15
+ * Main parser class for Xcode Instruments traces
16
+ */
17
+ export declare class TraceParser {
18
+ private xmlParser;
19
+ private exporter;
20
+ private exportAttempts;
21
+ constructor(exporter?: TraceExporter);
22
+ /**
23
+ * Parse a complete trace file
24
+ */
25
+ parseTrace(tracePath: string, options?: TraceParserOptions): Promise<ParsedTrace>;
26
+ /**
27
+ * Validate that the trace file exists and is readable
28
+ */
29
+ private validateTraceFile;
30
+ /**
31
+ * Extract metadata from trace file
32
+ */
33
+ private extractMetadataAndSchemas;
34
+ /**
35
+ * Parse Time Profiler data from trace
36
+ */
37
+ private parseTimeProfile;
38
+ /**
39
+ * Parse supported non-Time-Profiler instrument data.
40
+ */
41
+ private parseInstrumentAnalyses;
42
+ /**
43
+ * Parse main-thread hang events from `potential-hangs` and `hang-risks`.
44
+ *
45
+ * xctrace exposes these schemas in every macOS/iOS trace; each row carries a
46
+ * `start-time`, `duration`, and `hang-type` (`Hang` / `Severe Hang` /
47
+ * `Microhang`), plus thread/process metadata. Returns `undefined` when no
48
+ * hang schemas are present (most empty traces).
49
+ */
50
+ private parseHangs;
51
+ private parseHangRow;
52
+ private summarizeHangs;
53
+ private filterSamplesByTimeRange;
54
+ private filterHangEventsByTimeRange;
55
+ private timeProfileTotalDuration;
56
+ /**
57
+ * xctrace XML interns repeated values: the first occurrence has `id="N"`
58
+ * with full data, every subsequent occurrence is `<element ref="N"/>`.
59
+ * Without resolution every row after the first loses its thread/process
60
+ * info. Walk the rows once collecting `id -> node`, then deep-clone each
61
+ * row substituting any `ref` for its captured node.
62
+ */
63
+ private resolveIdRefs;
64
+ /**
65
+ * Read the duration of a `<start-time>` / `<duration>` element, in
66
+ * milliseconds. xctrace emits the raw nanosecond count as the element's
67
+ * text content and a pretty form (e.g. `"817.10 ms"` or `"00:01.326.520"`)
68
+ * as `@_fmt`. Prefer the text (always ns); fall back to fmt parsing.
69
+ */
70
+ private readDurationFieldMs;
71
+ private readTextField;
72
+ private readFmtField;
73
+ private readNumericField;
74
+ private parseNetworkAnalysis;
75
+ private tryExportHAR;
76
+ private analyzeRowsForKind;
77
+ private buildSupportStatus;
78
+ private exportAttemptsForSupportKind;
79
+ private statusFromExportAttempts;
80
+ private supportReason;
81
+ private unsupportedReason;
82
+ private instrumentSectionName;
83
+ private analyzeMemoryRows;
84
+ private analyzeAllocationRows;
85
+ private analyzeLeakRows;
86
+ private analyzeNetworkRows;
87
+ private analyzeNetworkHAR;
88
+ private analyzeEnergyRows;
89
+ private extractSchemas;
90
+ private extractGuiTrackNamesByKind;
91
+ private extractUserProcessNames;
92
+ private isAttachedTargetNode;
93
+ private processPath;
94
+ private processNameFromNode;
95
+ private isSystemProcessPath;
96
+ private extractTableDescriptors;
97
+ private unexportableFinding;
98
+ private matchSchemasForKind;
99
+ private exportRowsForSchemas;
100
+ private networkSchemasSafeForRawExport;
101
+ private unexportedRowsForSchemas;
102
+ private parseTableRows;
103
+ private parseXml;
104
+ private assertInputSize;
105
+ private limitRows;
106
+ private rowsFromTableNode;
107
+ private flattenRow;
108
+ private writeNestedValue;
109
+ private findFirstKey;
110
+ private findFirstKeyAtDepth;
111
+ private cleanKey;
112
+ private arrayOf;
113
+ private nodeName;
114
+ private xpathSegment;
115
+ private safeXPathElementName;
116
+ private xpathStringLiteral;
117
+ private parseScalar;
118
+ private parseNumeric;
119
+ private maxMetric;
120
+ private firstMetric;
121
+ private firstString;
122
+ private sumMatchingMetrics;
123
+ private pushByteMetric;
124
+ private pushNumberMetric;
125
+ private topRowByBytes;
126
+ private topMapEntry;
127
+ private hostFromURL;
128
+ private formatBytes;
129
+ /**
130
+ * Parse a single sample row from XML
131
+ */
132
+ private parseSampleRow;
133
+ private parseSampleTimestamp;
134
+ private parseSampleThreadId;
135
+ private parseSampleWeight;
136
+ private nodeScalar;
137
+ /**
138
+ * Aggregate function profiles from samples
139
+ */
140
+ private aggregateFunctionProfiles;
141
+ /**
142
+ * Parse function name to extract module and function
143
+ */
144
+ private parseFunctionName;
145
+ /**
146
+ * Parse duration string to milliseconds
147
+ */
148
+ private parseDuration;
149
+ }
150
+ /**
151
+ * Convenience function to parse a trace
152
+ */
153
+ export declare function parseTrace(tracePath: string, options?: TraceParserOptions): Promise<ParsedTrace>;
154
+ //# sourceMappingURL=trace-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-parser.d.ts","sourceRoot":"","sources":["../../src/parser/trace-parser.ts"],"names":[],"mappings":"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"}