@buoy-gg/highlight-updates 2.1.11 → 2.1.13
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/LICENSE +58 -0
- package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -285
- package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1371
- package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -591
- package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -267
- package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -178
- package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -303
- package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -500
- package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -830
- package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -894
- package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -220
- package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -70
- package/lib/commonjs/highlight-updates/components/index.js +1 -97
- package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1435
- package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -359
- package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
- package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -1828
- package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -903
- package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
- package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
- package/lib/commonjs/index.js +1 -311
- package/lib/commonjs/preset.js +1 -278
- package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -278
- package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1365
- package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -585
- package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -259
- package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -174
- package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -298
- package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -491
- package/lib/module/highlight-updates/components/RenderDetailView.js +1 -826
- package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -888
- package/lib/module/highlight-updates/components/RenderListItem.js +1 -215
- package/lib/module/highlight-updates/components/StatsDisplay.js +1 -67
- package/lib/module/highlight-updates/components/index.js +1 -16
- package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1431
- package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -353
- package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
- package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -1818
- package/lib/module/highlight-updates/utils/RenderTracker.js +1 -900
- package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
- package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
- package/lib/module/index.js +1 -71
- package/lib/module/preset.js +1 -272
- package/package.json +16 -16
- package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/index.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
|
@@ -1,359 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* PerformanceLogger
|
|
3
|
-
*
|
|
4
|
-
* Dedicated performance measurement utility for the Highlight Updates feature.
|
|
5
|
-
* Tracks timing metrics across the render detection pipeline to identify bottlenecks
|
|
6
|
-
* and measure optimization improvements.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* PerformanceLogger.setEnabled(true); // Enable logging
|
|
10
|
-
* const batch = PerformanceLogger.startBatch(nodesReceived);
|
|
11
|
-
* batch.markFilteringComplete(nodesFiltered, nodesToProcess);
|
|
12
|
-
* batch.markMeasurementComplete(successCount, failCount);
|
|
13
|
-
* batch.markTrackingComplete();
|
|
14
|
-
* batch.markCallbackComplete();
|
|
15
|
-
* batch.finish(); // Logs the complete metrics
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
"use strict";
|
|
19
|
-
|
|
20
|
-
// Declare performance API available in React Native's JavaScript environment
|
|
21
|
-
Object.defineProperty(exports, "__esModule", {
|
|
22
|
-
value: true
|
|
23
|
-
});
|
|
24
|
-
exports.default = exports.PerformanceLogger = void 0;
|
|
25
|
-
exports.markEventReceived = markEventReceived;
|
|
26
|
-
exports.markOverlayRendered = markOverlayRendered;
|
|
27
|
-
// Track the last event timestamp to measure end-to-end latency
|
|
28
|
-
let lastEventTimestamp = 0;
|
|
29
|
-
let pendingBatchId = null;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Call this when a traceUpdates event is received to track end-to-end latency
|
|
33
|
-
*/
|
|
34
|
-
function markEventReceived() {
|
|
35
|
-
lastEventTimestamp = performance.now();
|
|
36
|
-
return lastEventTimestamp;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Call this from the overlay when highlights are actually rendered
|
|
41
|
-
*/
|
|
42
|
-
function markOverlayRendered(highlightCount, renderTime) {
|
|
43
|
-
if (lastEventTimestamp > 0 && highlightCount > 0) {
|
|
44
|
-
// Reset to avoid double-counting (end-to-end logging removed - silent by default)
|
|
45
|
-
lastEventTimestamp = 0;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Rolling statistics for summary logging
|
|
50
|
-
|
|
51
|
-
class PerformanceLoggerSingleton {
|
|
52
|
-
enabled = false;
|
|
53
|
-
batchCounter = 0;
|
|
54
|
-
listeners = new Set();
|
|
55
|
-
|
|
56
|
-
// Rolling stats for periodic summaries
|
|
57
|
-
rollingStats = {
|
|
58
|
-
batchCount: 0,
|
|
59
|
-
totalNodes: 0,
|
|
60
|
-
totalFiltered: 0,
|
|
61
|
-
totalProcessed: 0,
|
|
62
|
-
totalTime: 0,
|
|
63
|
-
maxTime: 0,
|
|
64
|
-
minTime: Infinity,
|
|
65
|
-
avgMeasurementTime: 0
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Recent batch history for analysis
|
|
69
|
-
recentBatches = [];
|
|
70
|
-
MAX_HISTORY = 100;
|
|
71
|
-
|
|
72
|
-
// Summary logging interval
|
|
73
|
-
summaryInterval = null;
|
|
74
|
-
SUMMARY_INTERVAL_MS = 10000; // Log summary every 10s
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Enable or disable performance logging
|
|
78
|
-
*/
|
|
79
|
-
setEnabled(enabled) {
|
|
80
|
-
const wasEnabled = this.enabled;
|
|
81
|
-
this.enabled = enabled;
|
|
82
|
-
if (enabled && !wasEnabled) {
|
|
83
|
-
this.resetStats();
|
|
84
|
-
// Summary interval removed - no periodic logging
|
|
85
|
-
} else if (!enabled && wasEnabled) {
|
|
86
|
-
this.stopSummaryInterval();
|
|
87
|
-
}
|
|
88
|
-
// Silent enable/disable - no console logs
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Check if logging is enabled
|
|
93
|
-
*/
|
|
94
|
-
isEnabled() {
|
|
95
|
-
return this.enabled;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Start timing a new batch of render updates
|
|
100
|
-
*/
|
|
101
|
-
startBatch(nodesReceived, batchSize) {
|
|
102
|
-
const batchId = `batch_${++this.batchCounter}`;
|
|
103
|
-
const startTime = performance.now();
|
|
104
|
-
let filteringEndTime = null;
|
|
105
|
-
let measurementStartTime = null;
|
|
106
|
-
let measurementEndTime = null;
|
|
107
|
-
let trackingEndTime = null;
|
|
108
|
-
let callbackEndTime = null;
|
|
109
|
-
let nodesFiltered = 0;
|
|
110
|
-
let nodesToProcess = 0;
|
|
111
|
-
let measurementSuccessCount = 0;
|
|
112
|
-
let measurementFailCount = 0;
|
|
113
|
-
let overlayRenderTime;
|
|
114
|
-
const timer = {
|
|
115
|
-
markFilteringComplete: (filtered, toProcess) => {
|
|
116
|
-
filteringEndTime = performance.now();
|
|
117
|
-
nodesFiltered = filtered;
|
|
118
|
-
nodesToProcess = toProcess;
|
|
119
|
-
},
|
|
120
|
-
markMeasurementStart: () => {
|
|
121
|
-
measurementStartTime = performance.now();
|
|
122
|
-
},
|
|
123
|
-
markMeasurementComplete: (success, fail) => {
|
|
124
|
-
measurementEndTime = performance.now();
|
|
125
|
-
measurementSuccessCount = success;
|
|
126
|
-
measurementFailCount = fail;
|
|
127
|
-
},
|
|
128
|
-
markTrackingComplete: () => {
|
|
129
|
-
trackingEndTime = performance.now();
|
|
130
|
-
},
|
|
131
|
-
markCallbackComplete: () => {
|
|
132
|
-
callbackEndTime = performance.now();
|
|
133
|
-
},
|
|
134
|
-
setOverlayRenderTime: timeMs => {
|
|
135
|
-
overlayRenderTime = timeMs;
|
|
136
|
-
},
|
|
137
|
-
getBatchId: () => batchId,
|
|
138
|
-
finish: () => {
|
|
139
|
-
const endTime = performance.now();
|
|
140
|
-
const metrics = {
|
|
141
|
-
batchId,
|
|
142
|
-
timestamp: Date.now(),
|
|
143
|
-
nodesReceived,
|
|
144
|
-
nodesFiltered,
|
|
145
|
-
nodesToProcess,
|
|
146
|
-
batchSize,
|
|
147
|
-
nodesInBatch: Math.min(nodesToProcess, batchSize),
|
|
148
|
-
filteringTime: filteringEndTime ? filteringEndTime - startTime : 0,
|
|
149
|
-
measurementTime: measurementStartTime && measurementEndTime ? measurementEndTime - measurementStartTime : 0,
|
|
150
|
-
trackingTime: measurementEndTime && trackingEndTime ? trackingEndTime - measurementEndTime : 0,
|
|
151
|
-
callbackTime: trackingEndTime && callbackEndTime ? callbackEndTime - trackingEndTime : 0,
|
|
152
|
-
totalTime: endTime - startTime,
|
|
153
|
-
measurementSuccessCount,
|
|
154
|
-
measurementFailCount,
|
|
155
|
-
overlayRenderTime
|
|
156
|
-
};
|
|
157
|
-
if (this.enabled) {
|
|
158
|
-
this.recordMetrics(metrics);
|
|
159
|
-
}
|
|
160
|
-
return metrics;
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
return timer;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Record metrics and log them
|
|
168
|
-
*/
|
|
169
|
-
recordMetrics(metrics) {
|
|
170
|
-
// Update rolling stats
|
|
171
|
-
this.rollingStats.batchCount++;
|
|
172
|
-
this.rollingStats.totalNodes += metrics.nodesReceived;
|
|
173
|
-
this.rollingStats.totalFiltered += metrics.nodesFiltered;
|
|
174
|
-
this.rollingStats.totalProcessed += metrics.nodesInBatch;
|
|
175
|
-
this.rollingStats.totalTime += metrics.totalTime;
|
|
176
|
-
this.rollingStats.maxTime = Math.max(this.rollingStats.maxTime, metrics.totalTime);
|
|
177
|
-
this.rollingStats.minTime = Math.min(this.rollingStats.minTime, metrics.totalTime);
|
|
178
|
-
|
|
179
|
-
// Update rolling average for measurement time
|
|
180
|
-
const prevAvg = this.rollingStats.avgMeasurementTime;
|
|
181
|
-
const n = this.rollingStats.batchCount;
|
|
182
|
-
this.rollingStats.avgMeasurementTime = prevAvg + (metrics.measurementTime - prevAvg) / n;
|
|
183
|
-
|
|
184
|
-
// Store in history
|
|
185
|
-
this.recentBatches.push(metrics);
|
|
186
|
-
if (this.recentBatches.length > this.MAX_HISTORY) {
|
|
187
|
-
this.recentBatches.shift();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Notify listeners
|
|
191
|
-
this.notifyListeners(metrics);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Log a single batch's metrics
|
|
196
|
-
*/
|
|
197
|
-
logBatch(metrics) {
|
|
198
|
-
const {
|
|
199
|
-
batchId,
|
|
200
|
-
nodesReceived,
|
|
201
|
-
nodesFiltered,
|
|
202
|
-
nodesInBatch,
|
|
203
|
-
batchSize,
|
|
204
|
-
filteringTime,
|
|
205
|
-
measurementTime,
|
|
206
|
-
trackingTime,
|
|
207
|
-
callbackTime,
|
|
208
|
-
totalTime,
|
|
209
|
-
measurementSuccessCount,
|
|
210
|
-
measurementFailCount,
|
|
211
|
-
overlayRenderTime
|
|
212
|
-
} = metrics;
|
|
213
|
-
|
|
214
|
-
// Compact single-line log for quick scanning
|
|
215
|
-
console.log(`[HighlightPerf] ${batchId} | ` + `In:${nodesReceived} Filt:${nodesFiltered} Proc:${nodesInBatch}/${batchSize} | ` + `Filter:${filteringTime.toFixed(1)}ms Measure:${measurementTime.toFixed(1)}ms ` + `Track:${trackingTime.toFixed(1)}ms Callback:${callbackTime.toFixed(1)}ms | ` + `Total:${totalTime.toFixed(1)}ms` + (overlayRenderTime ? ` Render:${overlayRenderTime.toFixed(1)}ms` : "") + ` | Success:${measurementSuccessCount} Fail:${measurementFailCount}`);
|
|
216
|
-
|
|
217
|
-
// Flag slow batches
|
|
218
|
-
if (totalTime > 100) {
|
|
219
|
-
console.warn(`[HighlightPerf] ⚠️ SLOW BATCH: ${totalTime.toFixed(1)}ms - ` + `Measurement phase: ${measurementTime.toFixed(1)}ms (${(measurementTime / totalTime * 100).toFixed(0)}%)`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Log periodic summary stats
|
|
225
|
-
*/
|
|
226
|
-
logSummary() {
|
|
227
|
-
if (this.rollingStats.batchCount === 0) return;
|
|
228
|
-
const stats = this.rollingStats;
|
|
229
|
-
const avgTime = stats.totalTime / stats.batchCount;
|
|
230
|
-
const avgNodes = stats.totalNodes / stats.batchCount;
|
|
231
|
-
console.log(`\n[HighlightPerf] ════════ SUMMARY (last ${this.SUMMARY_INTERVAL_MS / 1000}s) ════════\n` + ` Batches: ${stats.batchCount}\n` + ` Avg nodes/batch: ${avgNodes.toFixed(1)} (filtered: ${(stats.totalFiltered / stats.batchCount).toFixed(1)})\n` + ` Avg total time: ${avgTime.toFixed(1)}ms\n` + ` Avg measurement time: ${stats.avgMeasurementTime.toFixed(1)}ms\n` + ` Min/Max time: ${stats.minTime.toFixed(1)}ms / ${stats.maxTime.toFixed(1)}ms\n` + `══════════════════════════════════════════════\n`);
|
|
232
|
-
|
|
233
|
-
// Reset rolling stats for next interval
|
|
234
|
-
this.resetStats();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Reset rolling statistics
|
|
239
|
-
*/
|
|
240
|
-
resetStats() {
|
|
241
|
-
this.rollingStats = {
|
|
242
|
-
batchCount: 0,
|
|
243
|
-
totalNodes: 0,
|
|
244
|
-
totalFiltered: 0,
|
|
245
|
-
totalProcessed: 0,
|
|
246
|
-
totalTime: 0,
|
|
247
|
-
maxTime: 0,
|
|
248
|
-
minTime: Infinity,
|
|
249
|
-
avgMeasurementTime: 0
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Start the summary logging interval
|
|
255
|
-
*/
|
|
256
|
-
startSummaryInterval() {
|
|
257
|
-
this.stopSummaryInterval();
|
|
258
|
-
this.summaryInterval = setInterval(() => {
|
|
259
|
-
this.logSummary();
|
|
260
|
-
}, this.SUMMARY_INTERVAL_MS);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Stop the summary logging interval
|
|
265
|
-
*/
|
|
266
|
-
stopSummaryInterval() {
|
|
267
|
-
if (this.summaryInterval) {
|
|
268
|
-
clearInterval(this.summaryInterval);
|
|
269
|
-
this.summaryInterval = null;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Subscribe to metrics updates
|
|
275
|
-
*/
|
|
276
|
-
subscribe(listener) {
|
|
277
|
-
this.listeners.add(listener);
|
|
278
|
-
return () => {
|
|
279
|
-
this.listeners.delete(listener);
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Notify all listeners of new metrics
|
|
285
|
-
*/
|
|
286
|
-
notifyListeners(metrics) {
|
|
287
|
-
for (const listener of this.listeners) {
|
|
288
|
-
try {
|
|
289
|
-
listener(metrics);
|
|
290
|
-
} catch (error) {
|
|
291
|
-
console.error("[HighlightPerf] Error in metrics listener:", error);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Get recent batch history
|
|
298
|
-
*/
|
|
299
|
-
getRecentBatches() {
|
|
300
|
-
return [...this.recentBatches];
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Get current rolling stats
|
|
305
|
-
*/
|
|
306
|
-
getRollingStats() {
|
|
307
|
-
return {
|
|
308
|
-
...this.rollingStats
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Clear all history and stats
|
|
314
|
-
*/
|
|
315
|
-
clear() {
|
|
316
|
-
this.recentBatches = [];
|
|
317
|
-
this.resetStats();
|
|
318
|
-
this.batchCounter = 0;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Generate a detailed report of recent performance
|
|
323
|
-
*/
|
|
324
|
-
generateReport() {
|
|
325
|
-
const batches = this.recentBatches;
|
|
326
|
-
if (batches.length === 0) {
|
|
327
|
-
return "No performance data collected yet.";
|
|
328
|
-
}
|
|
329
|
-
const totalTime = batches.reduce((sum, b) => sum + b.totalTime, 0);
|
|
330
|
-
const avgTime = totalTime / batches.length;
|
|
331
|
-
const totalMeasureTime = batches.reduce((sum, b) => sum + b.measurementTime, 0);
|
|
332
|
-
const avgMeasureTime = totalMeasureTime / batches.length;
|
|
333
|
-
const slowBatches = batches.filter(b => b.totalTime > 100);
|
|
334
|
-
const fastBatches = batches.filter(b => b.totalTime < 20);
|
|
335
|
-
const report = `
|
|
336
|
-
╔══════════════════════════════════════════════════════════════╗
|
|
337
|
-
║ HIGHLIGHT UPDATES PERFORMANCE REPORT ║
|
|
338
|
-
╠══════════════════════════════════════════════════════════════╣
|
|
339
|
-
║ Total batches analyzed: ${batches.length.toString().padStart(5)} ║
|
|
340
|
-
║ Average total time: ${avgTime.toFixed(1).padStart(5)}ms ║
|
|
341
|
-
║ Average measure time: ${avgMeasureTime.toFixed(1).padStart(5)}ms (${(avgMeasureTime / avgTime * 100).toFixed(0)}% of total) ║
|
|
342
|
-
╠══════════════════════════════════════════════════════════════╣
|
|
343
|
-
║ Fast batches (<20ms): ${fastBatches.length.toString().padStart(5)} (${(fastBatches.length / batches.length * 100).toFixed(0)}%) ║
|
|
344
|
-
║ Slow batches (>100ms): ${slowBatches.length.toString().padStart(5)} (${(slowBatches.length / batches.length * 100).toFixed(0)}%) ║
|
|
345
|
-
╠══════════════════════════════════════════════════════════════╣
|
|
346
|
-
║ Time breakdown (avg): ║
|
|
347
|
-
║ Filtering: ${batches.reduce((s, b) => s + b.filteringTime, 0 / batches.length).toFixed(1).padStart(6)}ms ║
|
|
348
|
-
║ Measurement: ${avgMeasureTime.toFixed(1).padStart(6)}ms ← Primary bottleneck ║
|
|
349
|
-
║ Tracking: ${(batches.reduce((s, b) => s + b.trackingTime, 0) / batches.length).toFixed(1).padStart(6)}ms ║
|
|
350
|
-
║ Callback: ${(batches.reduce((s, b) => s + b.callbackTime, 0) / batches.length).toFixed(1).padStart(6)}ms ║
|
|
351
|
-
╚══════════════════════════════════════════════════════════════╝
|
|
352
|
-
`;
|
|
353
|
-
return report;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Export singleton instance
|
|
358
|
-
const PerformanceLogger = exports.PerformanceLogger = new PerformanceLoggerSingleton();
|
|
359
|
-
var _default = exports.default = PerformanceLogger;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=exports.PerformanceLogger=void 0,exports.markEventReceived=markEventReceived,exports.markOverlayRendered=markOverlayRendered;let lastEventTimestamp=0,pendingBatchId=null;function markEventReceived(){return lastEventTimestamp=performance.now(),lastEventTimestamp}function markOverlayRendered(e,t){lastEventTimestamp>0&&e>0&&(lastEventTimestamp=0)}class PerformanceLoggerSingleton{enabled=!1;batchCounter=0;listeners=new Set;rollingStats={batchCount:0,totalNodes:0,totalFiltered:0,totalProcessed:0,totalTime:0,maxTime:0,minTime:1/0,avgMeasurementTime:0};recentBatches=[];MAX_HISTORY=100;summaryInterval=null;SUMMARY_INTERVAL_MS=1e4;setEnabled(e){const t=this.enabled;this.enabled=e,e&&!t?this.resetStats():!e&&t&&this.stopSummaryInterval()}isEnabled(){return this.enabled}startBatch(e,t){const a="batch_"+ ++this.batchCounter,n=performance.now();let r,i=null,s=null,o=null,l=null,m=null,c=0,h=0,d=0,g=0;return{markFilteringComplete:(e,t)=>{i=performance.now(),c=e,h=t},markMeasurementStart:()=>{s=performance.now()},markMeasurementComplete:(e,t)=>{o=performance.now(),d=e,g=t},markTrackingComplete:()=>{l=performance.now()},markCallbackComplete:()=>{m=performance.now()},setOverlayRenderTime:e=>{r=e},getBatchId:()=>a,finish:()=>{const u=performance.now(),T={batchId:a,timestamp:Date.now(),nodesReceived:e,nodesFiltered:c,nodesToProcess:h,batchSize:t,nodesInBatch:Math.min(h,t),filteringTime:i?i-n:0,measurementTime:s&&o?o-s:0,trackingTime:o&&l?l-o:0,callbackTime:l&&m?m-l:0,totalTime:u-n,measurementSuccessCount:d,measurementFailCount:g,overlayRenderTime:r};return this.enabled&&this.recordMetrics(T),T}}}recordMetrics(e){this.rollingStats.batchCount++,this.rollingStats.totalNodes+=e.nodesReceived,this.rollingStats.totalFiltered+=e.nodesFiltered,this.rollingStats.totalProcessed+=e.nodesInBatch,this.rollingStats.totalTime+=e.totalTime,this.rollingStats.maxTime=Math.max(this.rollingStats.maxTime,e.totalTime),this.rollingStats.minTime=Math.min(this.rollingStats.minTime,e.totalTime);const t=this.rollingStats.avgMeasurementTime,a=this.rollingStats.batchCount;this.rollingStats.avgMeasurementTime=t+(e.measurementTime-t)/a,this.recentBatches.push(e),this.recentBatches.length>this.MAX_HISTORY&&this.recentBatches.shift(),this.notifyListeners(e)}logBatch(e){const{batchId:t,nodesReceived:a,nodesFiltered:n,nodesInBatch:r,batchSize:i,filteringTime:s,measurementTime:o,trackingTime:l,callbackTime:m,totalTime:c,measurementSuccessCount:h,measurementFailCount:d,overlayRenderTime:g}=e;console.log(`[HighlightPerf] ${t} | In:${a} Filt:${n} Proc:${r}/${i} | Filter:${s.toFixed(1)}ms Measure:${o.toFixed(1)}ms Track:${l.toFixed(1)}ms Callback:${m.toFixed(1)}ms | Total:${c.toFixed(1)}ms`+(g?` Render:${g.toFixed(1)}ms`:"")+` | Success:${h} Fail:${d}`),c>100&&console.warn(`[HighlightPerf] ⚠️ SLOW BATCH: ${c.toFixed(1)}ms - Measurement phase: ${o.toFixed(1)}ms (${(o/c*100).toFixed(0)}%)`)}logSummary(){if(0===this.rollingStats.batchCount)return;const e=this.rollingStats,t=e.totalTime/e.batchCount,a=e.totalNodes/e.batchCount;console.log(`\n[HighlightPerf] ════════ SUMMARY (last ${this.SUMMARY_INTERVAL_MS/1e3}s) ════════\n Batches: ${e.batchCount}\n Avg nodes/batch: ${a.toFixed(1)} (filtered: ${(e.totalFiltered/e.batchCount).toFixed(1)})\n Avg total time: ${t.toFixed(1)}ms\n Avg measurement time: ${e.avgMeasurementTime.toFixed(1)}ms\n Min/Max time: ${e.minTime.toFixed(1)}ms / ${e.maxTime.toFixed(1)}ms\n══════════════════════════════════════════════\n`),this.resetStats()}resetStats(){this.rollingStats={batchCount:0,totalNodes:0,totalFiltered:0,totalProcessed:0,totalTime:0,maxTime:0,minTime:1/0,avgMeasurementTime:0}}startSummaryInterval(){this.stopSummaryInterval(),this.summaryInterval=setInterval(()=>{this.logSummary()},this.SUMMARY_INTERVAL_MS)}stopSummaryInterval(){this.summaryInterval&&(clearInterval(this.summaryInterval),this.summaryInterval=null)}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notifyListeners(e){for(const t of this.listeners)try{t(e)}catch(e){console.error("[HighlightPerf] Error in metrics listener:",e)}}getRecentBatches(){return[...this.recentBatches]}getRollingStats(){return{...this.rollingStats}}clear(){this.recentBatches=[],this.resetStats(),this.batchCounter=0}generateReport(){const e=this.recentBatches;if(0===e.length)return"No performance data collected yet.";const t=e.reduce((e,t)=>e+t.totalTime,0)/e.length,a=e.reduce((e,t)=>e+t.measurementTime,0)/e.length,n=e.filter(e=>e.totalTime>100),r=e.filter(e=>e.totalTime<20);return`\n╔══════════════════════════════════════════════════════════════╗\n║ HIGHLIGHT UPDATES PERFORMANCE REPORT ║\n╠══════════════════════════════════════════════════════════════╣\n║ Total batches analyzed: ${e.length.toString().padStart(5)} ║\n║ Average total time: ${t.toFixed(1).padStart(5)}ms ║\n║ Average measure time: ${a.toFixed(1).padStart(5)}ms (${(a/t*100).toFixed(0)}% of total) ║\n╠══════════════════════════════════════════════════════════════╣\n║ Fast batches (<20ms): ${r.length.toString().padStart(5)} (${(r.length/e.length*100).toFixed(0)}%) ║\n║ Slow batches (>100ms): ${n.length.toString().padStart(5)} (${(n.length/e.length*100).toFixed(0)}%) ║\n╠══════════════════════════════════════════════════════════════╣\n║ Time breakdown (avg): ║\n║ Filtering: ${e.reduce((e,t)=>e+t.filteringTime,0/e.length).toFixed(1).padStart(6)}ms ║\n║ Measurement: ${a.toFixed(1).padStart(6)}ms ← Primary bottleneck ║\n║ Tracking: ${(e.reduce((e,t)=>e+t.trackingTime,0)/e.length).toFixed(1).padStart(6)}ms ║\n║ Callback: ${(e.reduce((e,t)=>e+t.callbackTime,0)/e.length).toFixed(1).padStart(6)}ms ║\n╚══════════════════════════════════════════════════════════════╝\n`}}const PerformanceLogger=exports.PerformanceLogger=new PerformanceLoggerSingleton;var _default=exports.default=PerformanceLogger;
|