@sc4rfurryx/proteusjs 1.0.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 (82) hide show
  1. package/API.md +438 -0
  2. package/FEATURES.md +286 -0
  3. package/LICENSE +21 -0
  4. package/README.md +645 -0
  5. package/dist/.tsbuildinfo +1 -0
  6. package/dist/proteus.cjs.js +16014 -0
  7. package/dist/proteus.cjs.js.map +1 -0
  8. package/dist/proteus.d.ts +3018 -0
  9. package/dist/proteus.esm.js +16005 -0
  10. package/dist/proteus.esm.js.map +1 -0
  11. package/dist/proteus.esm.min.js +8 -0
  12. package/dist/proteus.esm.min.js.map +1 -0
  13. package/dist/proteus.js +16020 -0
  14. package/dist/proteus.js.map +1 -0
  15. package/dist/proteus.min.js +8 -0
  16. package/dist/proteus.min.js.map +1 -0
  17. package/package.json +98 -0
  18. package/src/__tests__/mvp-integration.test.ts +518 -0
  19. package/src/accessibility/AccessibilityEngine.ts +2106 -0
  20. package/src/accessibility/ScreenReaderSupport.ts +444 -0
  21. package/src/accessibility/__tests__/ScreenReaderSupport.test.ts +435 -0
  22. package/src/animations/FLIPAnimationSystem.ts +491 -0
  23. package/src/compatibility/BrowserCompatibility.ts +1076 -0
  24. package/src/containers/BreakpointSystem.ts +347 -0
  25. package/src/containers/ContainerBreakpoints.ts +726 -0
  26. package/src/containers/ContainerManager.ts +370 -0
  27. package/src/containers/ContainerUnits.ts +336 -0
  28. package/src/containers/ContextIsolation.ts +394 -0
  29. package/src/containers/ElementQueries.ts +411 -0
  30. package/src/containers/SmartContainer.ts +536 -0
  31. package/src/containers/SmartContainers.ts +376 -0
  32. package/src/containers/__tests__/ContainerBreakpoints.test.ts +411 -0
  33. package/src/containers/__tests__/SmartContainers.test.ts +281 -0
  34. package/src/content/ResponsiveImages.ts +570 -0
  35. package/src/core/EventSystem.ts +147 -0
  36. package/src/core/MemoryManager.ts +321 -0
  37. package/src/core/PerformanceMonitor.ts +238 -0
  38. package/src/core/PluginSystem.ts +275 -0
  39. package/src/core/ProteusJS.test.ts +164 -0
  40. package/src/core/ProteusJS.ts +962 -0
  41. package/src/developer/PerformanceProfiler.ts +567 -0
  42. package/src/developer/VisualDebuggingTools.ts +656 -0
  43. package/src/developer/ZeroConfigSystem.ts +593 -0
  44. package/src/index.ts +35 -0
  45. package/src/integration.test.ts +227 -0
  46. package/src/layout/AdaptiveGrid.ts +429 -0
  47. package/src/layout/ContentReordering.ts +532 -0
  48. package/src/layout/FlexboxEnhancer.ts +406 -0
  49. package/src/layout/FlowLayout.ts +545 -0
  50. package/src/layout/SpacingSystem.ts +512 -0
  51. package/src/observers/IntersectionObserverPolyfill.ts +289 -0
  52. package/src/observers/ObserverManager.ts +299 -0
  53. package/src/observers/ResizeObserverPolyfill.ts +179 -0
  54. package/src/performance/BatchDOMOperations.ts +519 -0
  55. package/src/performance/CSSOptimizationEngine.ts +646 -0
  56. package/src/performance/CacheOptimizationSystem.ts +601 -0
  57. package/src/performance/EfficientEventHandler.ts +740 -0
  58. package/src/performance/LazyEvaluationSystem.ts +532 -0
  59. package/src/performance/MemoryManagementSystem.ts +497 -0
  60. package/src/performance/PerformanceMonitor.ts +931 -0
  61. package/src/performance/__tests__/BatchDOMOperations.test.ts +309 -0
  62. package/src/performance/__tests__/EfficientEventHandler.test.ts +268 -0
  63. package/src/performance/__tests__/PerformanceMonitor.test.ts +422 -0
  64. package/src/polyfills/BrowserPolyfills.ts +586 -0
  65. package/src/polyfills/__tests__/BrowserPolyfills.test.ts +328 -0
  66. package/src/test/setup.ts +115 -0
  67. package/src/theming/SmartThemeSystem.ts +591 -0
  68. package/src/types/index.ts +134 -0
  69. package/src/typography/ClampScaling.ts +356 -0
  70. package/src/typography/FluidTypography.ts +759 -0
  71. package/src/typography/LineHeightOptimization.ts +430 -0
  72. package/src/typography/LineHeightOptimizer.ts +326 -0
  73. package/src/typography/TextFitting.ts +355 -0
  74. package/src/typography/TypographicScale.ts +428 -0
  75. package/src/typography/VerticalRhythm.ts +369 -0
  76. package/src/typography/__tests__/FluidTypography.test.ts +432 -0
  77. package/src/typography/__tests__/LineHeightOptimization.test.ts +436 -0
  78. package/src/utils/Logger.ts +173 -0
  79. package/src/utils/debounce.ts +259 -0
  80. package/src/utils/performance.ts +371 -0
  81. package/src/utils/support.ts +106 -0
  82. package/src/utils/version.ts +24 -0
@@ -0,0 +1,931 @@
1
+ /**
2
+ * PerformanceMonitor - Comprehensive performance monitoring and optimization
3
+ * Tracks frame rates, memory usage, and provides optimization recommendations
4
+ */
5
+
6
+ import { logger } from '../utils/Logger';
7
+
8
+ export interface PerformanceMetrics {
9
+ frameRate: number;
10
+ averageFPS: number;
11
+ averageFrameTime: number;
12
+ memoryUsage: {
13
+ used: number;
14
+ total: number;
15
+ percentage: number;
16
+ };
17
+ domNodes: number;
18
+ eventListeners: number;
19
+ observers: number;
20
+ cacheHitRate: number;
21
+ operationsPerSecond: number;
22
+ lastMeasurement: number;
23
+ }
24
+
25
+ export interface PerformanceThresholds {
26
+ minFrameRate: number;
27
+ maxFrameTime: number;
28
+ maxMemoryUsage: number;
29
+ maxDOMNodes: number;
30
+ maxEventListeners: number;
31
+ }
32
+
33
+ export interface PerformanceAlert {
34
+ type: 'warning' | 'critical';
35
+ metric: string;
36
+ value: number;
37
+ threshold: number;
38
+ message: string;
39
+ timestamp: number;
40
+ suggestions: string[];
41
+ }
42
+
43
+ export interface PerformanceSnapshot {
44
+ timestamp: number;
45
+ metrics: PerformanceMetrics;
46
+ bottlenecks: string[];
47
+ memoryLeaks: boolean;
48
+ }
49
+
50
+ export interface BottleneckInfo {
51
+ type: 'dom' | 'memory' | 'cpu' | 'network';
52
+ severity: 'low' | 'medium' | 'high';
53
+ description: string;
54
+ impact: number;
55
+ suggestions: string[];
56
+ }
57
+
58
+ class BottleneckDetector {
59
+ private detectedBottlenecks: BottleneckInfo[] = [];
60
+
61
+ public detectBottlenecks(metrics: PerformanceMetrics): BottleneckInfo[] {
62
+ this.detectedBottlenecks = [];
63
+
64
+ // CPU bottleneck detection
65
+ if (metrics.averageFPS < 30) {
66
+ this.detectedBottlenecks.push({
67
+ type: 'cpu',
68
+ severity: 'high',
69
+ description: 'Low frame rate detected',
70
+ impact: (30 - metrics.averageFPS) / 30,
71
+ suggestions: [
72
+ 'Reduce DOM manipulations',
73
+ 'Optimize JavaScript execution',
74
+ 'Use requestAnimationFrame for animations'
75
+ ]
76
+ });
77
+ }
78
+
79
+ // Memory bottleneck detection
80
+ if (metrics.memoryUsage.percentage > 80) {
81
+ this.detectedBottlenecks.push({
82
+ type: 'memory',
83
+ severity: 'high',
84
+ description: 'High memory usage detected',
85
+ impact: metrics.memoryUsage.percentage / 100,
86
+ suggestions: [
87
+ 'Clean up unused objects',
88
+ 'Remove event listeners',
89
+ 'Optimize image sizes'
90
+ ]
91
+ });
92
+ }
93
+
94
+ // DOM bottleneck detection
95
+ if (metrics.domNodes > 5000) {
96
+ this.detectedBottlenecks.push({
97
+ type: 'dom',
98
+ severity: 'medium',
99
+ description: 'Large DOM tree detected',
100
+ impact: Math.min(metrics.domNodes / 10000, 1),
101
+ suggestions: [
102
+ 'Implement virtual scrolling',
103
+ 'Remove unused DOM nodes',
104
+ 'Use document fragments for batch operations'
105
+ ]
106
+ });
107
+ }
108
+
109
+ return this.detectedBottlenecks;
110
+ }
111
+
112
+ public getBottlenecks(): BottleneckInfo[] {
113
+ return [...this.detectedBottlenecks];
114
+ }
115
+ }
116
+
117
+ class MemoryOptimizer {
118
+ private memoryLeakDetector: Map<string, number> = new Map();
119
+ private cleanupTasks: (() => void)[] = [];
120
+
121
+ public optimizeMemory(): void {
122
+ // Force garbage collection if available
123
+ if ((window as any).gc) {
124
+ (window as any).gc();
125
+ }
126
+
127
+ // Run cleanup tasks
128
+ this.cleanupTasks.forEach(task => {
129
+ try {
130
+ task();
131
+ } catch (error) {
132
+ logger.warn('Memory cleanup task failed:', error);
133
+ }
134
+ });
135
+
136
+ // Clear cleanup tasks
137
+ this.cleanupTasks = [];
138
+ }
139
+
140
+ public detectMemoryLeaks(metrics: PerformanceMetrics): boolean {
141
+ const currentMemory = metrics.memoryUsage.used;
142
+ const timestamp = Date.now();
143
+
144
+ // Store memory usage
145
+ this.memoryLeakDetector.set(timestamp.toString(), currentMemory);
146
+
147
+ // Keep only last 10 measurements
148
+ const entries = Array.from(this.memoryLeakDetector.entries());
149
+ if (entries.length > 10) {
150
+ entries.slice(0, -10).forEach(([key]) => {
151
+ this.memoryLeakDetector.delete(key);
152
+ });
153
+ }
154
+
155
+ // Detect consistent memory growth
156
+ if (entries.length >= 5) {
157
+ const values = entries.map(([, value]) => value);
158
+ const isIncreasing = values.every((val, i) => i === 0 || val >= (values[i - 1] || 0));
159
+ const lastValue = values[values.length - 1] || 0;
160
+ const firstValue = values[0] || 1;
161
+ const growthRate = (lastValue - firstValue) / firstValue;
162
+
163
+ return isIncreasing && growthRate > 0.1; // 10% growth
164
+ }
165
+
166
+ return false;
167
+ }
168
+
169
+ public addCleanupTask(task: () => void): void {
170
+ this.cleanupTasks.push(task);
171
+ }
172
+ }
173
+
174
+ export class PerformanceMonitor {
175
+ private metrics!: PerformanceMetrics;
176
+ private thresholds!: PerformanceThresholds;
177
+ private alerts: PerformanceAlert[] = [];
178
+ private isMonitoring: boolean = false;
179
+ private rafId: number | null = null;
180
+ private lastFrameTime: number = 0;
181
+ private frameCount: number = 0;
182
+ private bottleneckDetector: BottleneckDetector;
183
+ private memoryOptimizer: MemoryOptimizer;
184
+ private performanceHistory: PerformanceSnapshot[] = [];
185
+ private callbacks: Map<string, (metrics: PerformanceMetrics) => void> = new Map();
186
+ private measurementInterval: number = 1000; // 1 second
187
+ private detailedProfiling: boolean = false;
188
+ private frameTimes: number[] = [];
189
+ private operationCount: number = 0;
190
+ private lastOperationTime: number = 0;
191
+
192
+ constructor(thresholds: Partial<PerformanceThresholds> = {}) {
193
+ // Initialize advanced monitoring components
194
+ this.bottleneckDetector = new BottleneckDetector();
195
+ this.memoryOptimizer = new MemoryOptimizer();
196
+ this.thresholds = {
197
+ minFrameRate: 55, // Target 60fps with 5fps tolerance
198
+ maxFrameTime: 16.67, // 60fps = 16.67ms per frame
199
+ maxMemoryUsage: 100 * 1024 * 1024, // 100MB
200
+ maxDOMNodes: 5000,
201
+ maxEventListeners: 1000,
202
+ ...thresholds
203
+ };
204
+
205
+ this.metrics = this.createInitialMetrics();
206
+ }
207
+
208
+ /**
209
+ * Start performance monitoring (alias for start)
210
+ */
211
+ public startMonitoring(): void {
212
+ this.start();
213
+ }
214
+
215
+ /**
216
+ * Start performance monitoring
217
+ */
218
+ public start(): void {
219
+ if (this.isMonitoring) return;
220
+
221
+ this.isMonitoring = true;
222
+ this.lastFrameTime = performance.now();
223
+ this.lastOperationTime = performance.now();
224
+ this.startFrameMonitoring();
225
+ this.startMemoryMonitoring();
226
+ }
227
+
228
+ /**
229
+ * Stop performance monitoring
230
+ */
231
+ public stop(): void {
232
+ if (!this.isMonitoring) return;
233
+
234
+ this.isMonitoring = false;
235
+
236
+ if (this.rafId) {
237
+ cancelAnimationFrame(this.rafId);
238
+ this.rafId = null;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Destroy the performance monitor and clean up all resources
244
+ */
245
+ public destroy(): void {
246
+ this.stop();
247
+ this.callbacks.clear();
248
+ this.alerts = [];
249
+ this.frameTimes = [];
250
+ this.frameCount = 0;
251
+ this.operationCount = 0;
252
+ this.metrics = this.createInitialMetrics();
253
+ }
254
+
255
+ /**
256
+ * Start frame rate monitoring
257
+ */
258
+ public startFrameRateMonitoring(): void {
259
+ if (this.isMonitoring) {
260
+ return;
261
+ }
262
+ this.start();
263
+ }
264
+
265
+ /**
266
+ * Stop frame rate monitoring
267
+ */
268
+ public stopFrameRateMonitoring(): void {
269
+ this.stop();
270
+ }
271
+
272
+ /**
273
+ * Measure operation performance
274
+ */
275
+ public async measureOperation<T>(name: string, operation: () => Promise<T> | T): Promise<{ result: T; duration: number; name: string }> {
276
+ const startTime = performance.now();
277
+ const result = await operation();
278
+ const duration = performance.now() - startTime;
279
+
280
+ this.recordOperation();
281
+
282
+ return { result, duration, name };
283
+ }
284
+
285
+ /**
286
+ * Detect performance bottlenecks
287
+ */
288
+ public detectBottlenecks(): Array<{ type: string; severity: 'low' | 'medium' | 'high'; description: string }> {
289
+ const bottlenecks: Array<{ type: string; severity: 'low' | 'medium' | 'high'; description: string }> = [];
290
+
291
+ // Check frame rate
292
+ if (this.metrics.averageFPS < 30) {
293
+ bottlenecks.push({
294
+ type: 'frame-rate',
295
+ severity: 'high',
296
+ description: `Low frame rate: ${this.metrics.averageFPS.toFixed(1)} FPS`
297
+ });
298
+ } else if (this.metrics.averageFPS < 50) {
299
+ bottlenecks.push({
300
+ type: 'frame-rate',
301
+ severity: 'medium',
302
+ description: `Moderate frame rate: ${this.metrics.averageFPS.toFixed(1)} FPS`
303
+ });
304
+ }
305
+
306
+ // Check memory usage
307
+ if (this.metrics.memoryUsage.percentage > 80) {
308
+ bottlenecks.push({
309
+ type: 'memory',
310
+ severity: 'high',
311
+ description: `High memory usage: ${this.metrics.memoryUsage.percentage.toFixed(1)}%`
312
+ });
313
+ }
314
+
315
+ return bottlenecks;
316
+ }
317
+
318
+ /**
319
+ * Get current performance metrics
320
+ */
321
+ public getMetrics(): PerformanceMetrics {
322
+ // Update metrics before returning them
323
+ this.updateMetrics();
324
+ return { ...this.metrics };
325
+ }
326
+
327
+ /**
328
+ * Get performance alerts
329
+ */
330
+ public getAlerts(): PerformanceAlert[] {
331
+ return [...this.alerts];
332
+ }
333
+
334
+ /**
335
+ * Clear performance alerts
336
+ */
337
+ public clearAlerts(): void {
338
+ this.alerts = [];
339
+ }
340
+
341
+ /**
342
+ * Add performance monitoring callback
343
+ */
344
+ public addCallback(id: string, callback: (metrics: PerformanceMetrics) => void): void {
345
+ this.callbacks.set(id, callback);
346
+ }
347
+
348
+ /**
349
+ * Remove performance monitoring callback
350
+ */
351
+ public removeCallback(id: string): void {
352
+ this.callbacks.delete(id);
353
+ }
354
+
355
+ /**
356
+ * Record an operation for performance tracking
357
+ */
358
+ public recordOperation(): void {
359
+ this.operationCount++;
360
+ }
361
+
362
+ /**
363
+ * Update cache hit rate
364
+ */
365
+ public updateCacheHitRate(hits: number, total: number): void {
366
+ this.metrics.cacheHitRate = total > 0 ? (hits / total) * 100 : 0;
367
+ }
368
+
369
+ /**
370
+ * Force immediate metrics update
371
+ */
372
+ public updateMetrics(): void {
373
+ this.updateFrameMetrics();
374
+ this.updateMemoryMetrics();
375
+ this.updateDOMMetrics();
376
+ this.updateOperationMetrics();
377
+ this.checkThresholds();
378
+ this.notifyCallbacks();
379
+ }
380
+
381
+ /**
382
+ * Get performance recommendations
383
+ */
384
+ public getRecommendations(): string[] {
385
+ const recommendations: string[] = [];
386
+
387
+ if (this.metrics.frameRate < this.thresholds.minFrameRate) {
388
+ recommendations.push('Consider reducing DOM manipulations or using requestAnimationFrame');
389
+ recommendations.push('Enable batch DOM operations to improve frame rate');
390
+ }
391
+
392
+ if (this.metrics.memoryUsage.percentage > 80) {
393
+ recommendations.push('Memory usage is high - consider implementing cleanup routines');
394
+ recommendations.push('Review event listeners and observers for potential leaks');
395
+ }
396
+
397
+ if (this.metrics.domNodes > this.thresholds.maxDOMNodes) {
398
+ recommendations.push('DOM tree is large - consider virtualization for long lists');
399
+ recommendations.push('Remove unused DOM elements to improve performance');
400
+ }
401
+
402
+ if (this.metrics.eventListeners > this.thresholds.maxEventListeners) {
403
+ recommendations.push('High number of event listeners - consider event delegation');
404
+ recommendations.push('Review and cleanup unused event listeners');
405
+ }
406
+
407
+ if (this.metrics.cacheHitRate < 70) {
408
+ recommendations.push('Cache hit rate is low - review caching strategy');
409
+ recommendations.push('Consider increasing cache size or improving cache keys');
410
+ }
411
+
412
+ return recommendations;
413
+ }
414
+
415
+ /**
416
+ * Start frame rate monitoring
417
+ */
418
+ private startFrameMonitoring(): void {
419
+ const measureFrame = (timestamp: number) => {
420
+ if (!this.isMonitoring) return;
421
+
422
+ const deltaTime = timestamp - this.lastFrameTime;
423
+ this.frameTimes.push(deltaTime);
424
+
425
+ // Keep only last 60 frames for rolling average
426
+ if (this.frameTimes.length > 60) {
427
+ this.frameTimes.shift();
428
+ }
429
+
430
+ this.frameCount++;
431
+ this.lastFrameTime = timestamp;
432
+
433
+ // Update metrics every 60 frames or 1 second
434
+ if (this.frameCount % 60 === 0 || deltaTime > 1000) {
435
+ this.updateFrameMetrics();
436
+ this.checkThresholds();
437
+ this.notifyCallbacks();
438
+ }
439
+
440
+ this.rafId = requestAnimationFrame(measureFrame);
441
+ };
442
+
443
+ this.rafId = requestAnimationFrame(measureFrame);
444
+ }
445
+
446
+ /**
447
+ * Start memory monitoring
448
+ */
449
+ private startMemoryMonitoring(): void {
450
+ // Update memory metrics every 5 seconds
451
+ const updateMemory = () => {
452
+ if (!this.isMonitoring) return;
453
+
454
+ this.updateMemoryMetrics();
455
+ setTimeout(updateMemory, 5000);
456
+ };
457
+
458
+ setTimeout(updateMemory, 5000);
459
+ }
460
+
461
+ /**
462
+ * Update frame-related metrics
463
+ */
464
+ private updateFrameMetrics(): void {
465
+ if (this.frameTimes.length === 0) return;
466
+
467
+ const averageFrameTime = this.frameTimes.reduce((sum, time) => sum + time, 0) / this.frameTimes.length;
468
+ const frameRate = averageFrameTime > 0 ? 1000 / averageFrameTime : 60; // Fallback to 60fps
469
+
470
+ this.metrics.averageFrameTime = Math.round(averageFrameTime * 100) / 100;
471
+ this.metrics.frameRate = Math.round(frameRate * 100) / 100;
472
+ this.metrics.averageFPS = this.metrics.frameRate; // Keep them in sync
473
+ this.metrics.lastMeasurement = performance.now();
474
+ }
475
+
476
+ /**
477
+ * Update memory-related metrics
478
+ */
479
+ private updateMemoryMetrics(): void {
480
+ if ('memory' in performance) {
481
+ const memory = (performance as any).memory;
482
+ this.metrics.memoryUsage = {
483
+ used: memory.usedJSHeapSize,
484
+ total: memory.totalJSHeapSize,
485
+ percentage: Math.round((memory.usedJSHeapSize / memory.totalJSHeapSize) * 100)
486
+ };
487
+ }
488
+ }
489
+
490
+ /**
491
+ * Update DOM-related metrics
492
+ */
493
+ private updateDOMMetrics(): void {
494
+ this.metrics.domNodes = document.querySelectorAll('*').length;
495
+
496
+ // Estimate event listeners (this is approximate)
497
+ this.metrics.eventListeners = this.estimateEventListeners();
498
+
499
+ // Count observers (ResizeObserver, IntersectionObserver, etc.)
500
+ this.metrics.observers = this.countObservers();
501
+ }
502
+
503
+ /**
504
+ * Update operation metrics
505
+ */
506
+ private updateOperationMetrics(): void {
507
+ const now = performance.now();
508
+ const timeDelta = (now - this.lastOperationTime) / 1000; // Convert to seconds
509
+
510
+ if (timeDelta > 0) {
511
+ this.metrics.operationsPerSecond = Math.round(this.operationCount / timeDelta);
512
+ }
513
+
514
+ this.operationCount = 0;
515
+ this.lastOperationTime = now;
516
+ }
517
+
518
+ /**
519
+ * Estimate number of event listeners
520
+ */
521
+ private estimateEventListeners(): number {
522
+ // This is an approximation - actual count would require tracking
523
+ const elements = document.querySelectorAll('*');
524
+ let count = 0;
525
+
526
+ // Common events that are likely to have listeners
527
+ const commonEvents = ['click', 'scroll', 'resize', 'load', 'input', 'change'];
528
+
529
+ elements.forEach(element => {
530
+ commonEvents.forEach(event => {
531
+ if ((element as any)[`on${event}`] !== null) {
532
+ count++;
533
+ }
534
+ });
535
+ });
536
+
537
+ return count;
538
+ }
539
+
540
+ /**
541
+ * Count active observers
542
+ */
543
+ private countObservers(): number {
544
+ // This would need to be integrated with actual observer tracking
545
+ // For now, return an estimate
546
+ return 0;
547
+ }
548
+
549
+ /**
550
+ * Check performance thresholds and generate alerts
551
+ */
552
+ private checkThresholds(): void {
553
+ const now = performance.now();
554
+
555
+ // Check frame rate
556
+ if (this.metrics.frameRate < this.thresholds.minFrameRate) {
557
+ this.addAlert({
558
+ type: 'warning',
559
+ metric: 'frameRate',
560
+ value: this.metrics.frameRate,
561
+ threshold: this.thresholds.minFrameRate,
562
+ message: `Frame rate (${this.metrics.frameRate}fps) is below target (${this.thresholds.minFrameRate}fps)`,
563
+ timestamp: now,
564
+ suggestions: [
565
+ 'Reduce DOM manipulations',
566
+ 'Use requestAnimationFrame for animations',
567
+ 'Enable batch DOM operations'
568
+ ]
569
+ });
570
+ }
571
+
572
+ // Check memory usage
573
+ if (this.metrics.memoryUsage.used > this.thresholds.maxMemoryUsage) {
574
+ this.addAlert({
575
+ type: 'critical',
576
+ metric: 'memoryUsage',
577
+ value: this.metrics.memoryUsage.used,
578
+ threshold: this.thresholds.maxMemoryUsage,
579
+ message: `Memory usage (${Math.round(this.metrics.memoryUsage.used / 1024 / 1024)}MB) exceeds threshold`,
580
+ timestamp: now,
581
+ suggestions: [
582
+ 'Implement cleanup routines',
583
+ 'Review for memory leaks',
584
+ 'Optimize data structures'
585
+ ]
586
+ });
587
+ }
588
+
589
+ // Check DOM nodes
590
+ if (this.metrics.domNodes > this.thresholds.maxDOMNodes) {
591
+ this.addAlert({
592
+ type: 'warning',
593
+ metric: 'domNodes',
594
+ value: this.metrics.domNodes,
595
+ threshold: this.thresholds.maxDOMNodes,
596
+ message: `DOM tree size (${this.metrics.domNodes} nodes) is large`,
597
+ timestamp: now,
598
+ suggestions: [
599
+ 'Consider virtualization',
600
+ 'Remove unused elements',
601
+ 'Optimize DOM structure'
602
+ ]
603
+ });
604
+ }
605
+ }
606
+
607
+ /**
608
+ * Add performance alert
609
+ */
610
+ private addAlert(alert: PerformanceAlert): void {
611
+ // Avoid duplicate alerts for the same metric within 30 seconds
612
+ const recentAlert = this.alerts.find(a =>
613
+ a.metric === alert.metric &&
614
+ alert.timestamp - a.timestamp < 30000
615
+ );
616
+
617
+ if (!recentAlert) {
618
+ this.alerts.push(alert);
619
+
620
+ // Keep only last 50 alerts
621
+ if (this.alerts.length > 50) {
622
+ this.alerts.shift();
623
+ }
624
+ }
625
+ }
626
+
627
+ /**
628
+ * Notify callbacks of metrics update
629
+ */
630
+ private notifyCallbacks(): void {
631
+ this.callbacks.forEach(callback => {
632
+ try {
633
+ callback(this.metrics);
634
+ } catch (error) {
635
+ logger.error('Error in performance callback', error);
636
+ }
637
+ });
638
+ }
639
+
640
+ /**
641
+ * Create initial metrics object
642
+ */
643
+ private createInitialMetrics(): PerformanceMetrics {
644
+ return {
645
+ frameRate: 60,
646
+ averageFPS: 60,
647
+ averageFrameTime: 16.67,
648
+ memoryUsage: {
649
+ used: 0,
650
+ total: 0,
651
+ percentage: 0
652
+ },
653
+ domNodes: 0,
654
+ eventListeners: 0,
655
+ observers: 0,
656
+ cacheHitRate: 0,
657
+ operationsPerSecond: 0,
658
+ lastMeasurement: performance.now()
659
+ };
660
+ }
661
+
662
+ /**
663
+ * Advanced performance monitoring methods
664
+ */
665
+
666
+ /**
667
+ * Enable detailed profiling with comprehensive metrics
668
+ */
669
+ public enableDetailedProfiling(enable: boolean = true): void {
670
+ this.detailedProfiling = enable;
671
+
672
+ if (enable) {
673
+ this.startAdvancedMonitoring();
674
+ } else {
675
+ this.stopAdvancedMonitoring();
676
+ }
677
+ }
678
+
679
+ /**
680
+ * Start advanced monitoring with bottleneck detection
681
+ */
682
+ private startAdvancedMonitoring(): void {
683
+ // Enhanced frame rate monitoring
684
+ this.startFrameRateMonitoring();
685
+
686
+ // Memory leak detection
687
+ setInterval(() => {
688
+ const metrics = this.getMetrics();
689
+ const hasMemoryLeak = this.memoryOptimizer.detectMemoryLeaks(metrics);
690
+
691
+ if (hasMemoryLeak) {
692
+ this.addAlert({
693
+ type: 'warning',
694
+ metric: 'memory',
695
+ value: metrics.memoryUsage.percentage,
696
+ threshold: 80,
697
+ message: 'Potential memory leak detected',
698
+ timestamp: Date.now(),
699
+ suggestions: [
700
+ 'Check for unreferenced objects',
701
+ 'Remove unused event listeners',
702
+ 'Clear intervals and timeouts'
703
+ ]
704
+ });
705
+ }
706
+ }, 5000);
707
+
708
+ // Bottleneck detection
709
+ setInterval(() => {
710
+ const metrics = this.getMetrics();
711
+ const bottlenecks = this.bottleneckDetector.detectBottlenecks(metrics);
712
+
713
+ bottlenecks.forEach(bottleneck => {
714
+ if (bottleneck.severity === 'high') {
715
+ this.addAlert({
716
+ type: 'critical',
717
+ metric: bottleneck.type,
718
+ value: bottleneck.impact * 100,
719
+ threshold: 50,
720
+ message: bottleneck.description,
721
+ timestamp: Date.now(),
722
+ suggestions: bottleneck.suggestions
723
+ });
724
+ }
725
+ });
726
+ }, 2000);
727
+ }
728
+
729
+ /**
730
+ * Stop advanced monitoring
731
+ */
732
+ private stopAdvancedMonitoring(): void {
733
+ // This would clear the intervals set in startAdvancedMonitoring
734
+ // For simplicity, we'll just log that advanced monitoring is stopped
735
+ logger.info('Advanced performance monitoring stopped');
736
+ }
737
+
738
+ /**
739
+ * Get comprehensive performance snapshot
740
+ */
741
+ public getPerformanceSnapshot(): PerformanceSnapshot {
742
+ const metrics = this.getMetrics();
743
+ const bottlenecks = this.bottleneckDetector.getBottlenecks().map(b => b.description);
744
+ const memoryLeaks = this.memoryOptimizer.detectMemoryLeaks(metrics);
745
+
746
+ const snapshot: PerformanceSnapshot = {
747
+ timestamp: Date.now(),
748
+ metrics,
749
+ bottlenecks,
750
+ memoryLeaks
751
+ };
752
+
753
+ // Store in history
754
+ this.performanceHistory.push(snapshot);
755
+
756
+ // Keep only last 100 snapshots
757
+ if (this.performanceHistory.length > 100) {
758
+ this.performanceHistory.shift();
759
+ }
760
+
761
+ return snapshot;
762
+ }
763
+
764
+ /**
765
+ * Get performance history for analysis
766
+ */
767
+ public getPerformanceHistory(): PerformanceSnapshot[] {
768
+ return [...this.performanceHistory];
769
+ }
770
+
771
+ /**
772
+ * Analyze performance trends
773
+ */
774
+ public analyzePerformanceTrends(): {
775
+ frameRateTrend: 'improving' | 'degrading' | 'stable';
776
+ memoryTrend: 'improving' | 'degrading' | 'stable';
777
+ overallHealth: 'good' | 'warning' | 'critical';
778
+ } {
779
+ if (this.performanceHistory.length < 5) {
780
+ return {
781
+ frameRateTrend: 'stable',
782
+ memoryTrend: 'stable',
783
+ overallHealth: 'good'
784
+ };
785
+ }
786
+
787
+ const recent = this.performanceHistory.slice(-5);
788
+ const frameRates = recent.map(s => s.metrics.averageFPS);
789
+ const memoryUsages = recent.map(s => s.metrics.memoryUsage.percentage);
790
+
791
+ // Analyze frame rate trend
792
+ const frameRateSlope = this.calculateTrend(frameRates);
793
+ const frameRateTrend = frameRateSlope > 1 ? 'improving' :
794
+ frameRateSlope < -1 ? 'degrading' : 'stable';
795
+
796
+ // Analyze memory trend
797
+ const memorySlope = this.calculateTrend(memoryUsages);
798
+ const memoryTrend = memorySlope < -5 ? 'improving' :
799
+ memorySlope > 5 ? 'degrading' : 'stable';
800
+
801
+ // Overall health assessment
802
+ const currentMetrics = recent[recent.length - 1]?.metrics;
803
+ let overallHealth: 'good' | 'warning' | 'critical' = 'good';
804
+
805
+ if (currentMetrics) {
806
+ if (currentMetrics.averageFPS < 30 || currentMetrics.memoryUsage.percentage > 80) {
807
+ overallHealth = 'critical';
808
+ } else if (currentMetrics.averageFPS < 45 || currentMetrics.memoryUsage.percentage > 60) {
809
+ overallHealth = 'warning';
810
+ }
811
+ }
812
+
813
+ return {
814
+ frameRateTrend,
815
+ memoryTrend,
816
+ overallHealth
817
+ };
818
+ }
819
+
820
+ /**
821
+ * Calculate trend slope for a series of values
822
+ */
823
+ private calculateTrend(values: number[]): number {
824
+ if (values.length < 2) return 0;
825
+
826
+ const n = values.length;
827
+ const sumX = (n * (n - 1)) / 2;
828
+ const sumY = values.reduce((a, b) => a + b, 0);
829
+ const sumXY = values.reduce((sum, y, x) => sum + x * y, 0);
830
+ const sumXX = values.reduce((sum, _, x) => sum + x * x, 0);
831
+
832
+ return (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
833
+ }
834
+
835
+ /**
836
+ * Optimize performance based on current metrics
837
+ */
838
+ public optimizePerformance(): void {
839
+ const metrics = this.getMetrics();
840
+ const bottlenecks = this.bottleneckDetector.detectBottlenecks(metrics);
841
+
842
+ // Apply memory optimization if needed
843
+ if (metrics.memoryUsage.percentage > 70) {
844
+ this.memoryOptimizer.optimizeMemory();
845
+ logger.info('Memory optimization applied');
846
+ }
847
+
848
+ // Apply DOM optimization
849
+ if (metrics.domNodes > 3000) {
850
+ this.optimizeDOM();
851
+ }
852
+
853
+ // Log optimization results
854
+ bottlenecks.forEach(bottleneck => {
855
+ logger.info(`Performance bottleneck detected: ${bottleneck.description}`);
856
+ logger.info(`Suggestions: ${bottleneck.suggestions.join(', ')}`);
857
+ });
858
+ }
859
+
860
+ /**
861
+ * Optimize DOM performance
862
+ */
863
+ private optimizeDOM(): void {
864
+ // Remove unused elements
865
+ const unusedElements = document.querySelectorAll('[data-proteus-unused]');
866
+ unusedElements.forEach(el => el.remove());
867
+
868
+ // Optimize images
869
+ const images = document.querySelectorAll('img:not([loading])');
870
+ images.forEach(img => {
871
+ (img as HTMLImageElement).loading = 'lazy';
872
+ });
873
+
874
+ logger.info(`DOM optimization applied: removed ${unusedElements.length} unused elements, optimized ${images.length} images`);
875
+ }
876
+
877
+ /**
878
+ * Generate performance report
879
+ */
880
+ public generatePerformanceReport(): {
881
+ summary: string;
882
+ metrics: PerformanceMetrics;
883
+ bottlenecks: BottleneckInfo[];
884
+ trends: {
885
+ frameRateTrend: 'improving' | 'degrading' | 'stable';
886
+ memoryTrend: 'improving' | 'degrading' | 'stable';
887
+ overallHealth: 'good' | 'warning' | 'critical';
888
+ };
889
+ recommendations: string[];
890
+ } {
891
+ const metrics = this.getMetrics();
892
+ const bottlenecks = this.bottleneckDetector.detectBottlenecks(metrics);
893
+ const trends = this.analyzePerformanceTrends();
894
+
895
+ const recommendations: string[] = [];
896
+
897
+ // Generate recommendations based on metrics
898
+ if (metrics.averageFPS < 45) {
899
+ recommendations.push('Consider reducing animation complexity');
900
+ recommendations.push('Optimize JavaScript execution with requestAnimationFrame');
901
+ }
902
+
903
+ if (metrics.memoryUsage.percentage > 60) {
904
+ recommendations.push('Implement memory cleanup strategies');
905
+ recommendations.push('Remove unused event listeners and observers');
906
+ }
907
+
908
+ if (metrics.domNodes > 2000) {
909
+ recommendations.push('Consider virtual scrolling for large lists');
910
+ recommendations.push('Remove unused DOM elements');
911
+ }
912
+
913
+ // Add bottleneck-specific recommendations
914
+ bottlenecks.forEach(bottleneck => {
915
+ recommendations.push(...bottleneck.suggestions);
916
+ });
917
+
918
+ const summary = `Performance Health: ${trends.overallHealth.toUpperCase()} | ` +
919
+ `FPS: ${metrics.averageFPS.toFixed(1)} | ` +
920
+ `Memory: ${metrics.memoryUsage.percentage.toFixed(1)}% | ` +
921
+ `DOM Nodes: ${metrics.domNodes}`;
922
+
923
+ return {
924
+ summary,
925
+ metrics,
926
+ bottlenecks,
927
+ trends,
928
+ recommendations: [...new Set(recommendations)] // Remove duplicates
929
+ };
930
+ }
931
+ }