performance.ts
1 // Performance monitoring utilities 2 3 interface PerformanceMetric { 4 name: string; 5 startTime: number; 6 endTime?: number; 7 duration?: number; 8 } 9 10 class PerformanceMonitor { 11 private static instance: PerformanceMonitor; 12 private metrics: Map<string, PerformanceMetric> = new Map(); 13 private isEnabled: boolean = __DEV__; // Only enable in development 14 15 private constructor() {} 16 17 static getInstance(): PerformanceMonitor { 18 if (!PerformanceMonitor.instance) { 19 PerformanceMonitor.instance = new PerformanceMonitor(); 20 } 21 return PerformanceMonitor.instance; 22 } 23 24 startMeasure(name: string): void { 25 if (!this.isEnabled) return; 26 27 this.metrics.set(name, { 28 name, 29 startTime: performance.now(), 30 }); 31 } 32 33 endMeasure(name: string): number | null { 34 if (!this.isEnabled) return null; 35 36 const metric = this.metrics.get(name); 37 if (!metric) { 38 console.warn(`Performance metric "${name}" was not started`); 39 return null; 40 } 41 42 const endTime = performance.now(); 43 const duration = endTime - metric.startTime; 44 45 metric.endTime = endTime; 46 metric.duration = duration; 47 48 if (duration > 100) { 49 // Log slow operations (>100ms) 50 console.log(`[Performance] ${name}: ${duration.toFixed(2)}ms`); 51 } 52 53 return duration; 54 } 55 56 measureAsync<T>(name: string, operation: () => Promise<T>): Promise<T> { 57 if (!this.isEnabled) return operation(); 58 59 this.startMeasure(name); 60 return operation().finally(() => { 61 this.endMeasure(name); 62 }); 63 } 64 65 measureSync<T>(name: string, operation: () => T): T { 66 if (!this.isEnabled) return operation(); 67 68 this.startMeasure(name); 69 try { 70 return operation(); 71 } finally { 72 this.endMeasure(name); 73 } 74 } 75 76 getMetrics(): PerformanceMetric[] { 77 return Array.from(this.metrics.values()); 78 } 79 80 clearMetrics(): void { 81 this.metrics.clear(); 82 } 83 84 enable(): void { 85 this.isEnabled = true; 86 } 87 88 disable(): void { 89 this.isEnabled = false; 90 } 91 } 92 93 export const performanceMonitor = PerformanceMonitor.getInstance(); 94 95 // React hook for measuring component render times 96 export function useRenderTime(componentName: string) { 97 if (__DEV__) { 98 performanceMonitor.startMeasure(`render:${componentName}`); 99 100 return () => { 101 performanceMonitor.endMeasure(`render:${componentName}`); 102 }; 103 } 104 105 return () => {}; // No-op in production 106 } 107 108 // Decorator for measuring function execution time 109 export function measureExecutionTime( 110 target: any, 111 propertyName: string, 112 descriptor: PropertyDescriptor 113 ) { 114 if (!__DEV__) return descriptor; 115 116 const method = descriptor.value; 117 118 descriptor.value = function (...args: any[]) { 119 const functionName = `${target.constructor.name}.${propertyName}`; 120 return performanceMonitor.measureSync(functionName, () => 121 method.apply(this, args) 122 ); 123 }; 124 125 return descriptor; 126 } 127 128 // Utility for measuring component lifecycle 129 export function measureComponentLifecycle(ComponentClass: any) { 130 if (!__DEV__) return ComponentClass; 131 132 const originalRender = ComponentClass.prototype.render; 133 const componentName = ComponentClass.name; 134 135 ComponentClass.prototype.render = function () { 136 const endMeasure = useRenderTime(componentName); 137 const result = originalRender.call(this); 138 endMeasure(); 139 return result; 140 }; 141 142 return ComponentClass; 143 } 144 145 export default performanceMonitor;