chore: lint

This commit is contained in:
amhsirak
2025-03-04 22:37:03 +05:30
parent 26688b4b45
commit 941ae93648

View File

@@ -104,250 +104,250 @@ export class EnhancedPerformanceMonitor extends FrontendPerformanceMonitor {
private memoryCheckInterval: NodeJS.Timeout | null = null; private memoryCheckInterval: NodeJS.Timeout | null = null;
constructor(options?: { constructor(options?: {
memoryWarningThreshold?: number, memoryWarningThreshold?: number,
maxMetricsHistory?: number, maxMetricsHistory?: number,
memoryAlertCallback?: (usage: MemoryInfo) => void memoryAlertCallback?: (usage: MemoryInfo) => void
}) { }) {
super(); super();
if (options) { if (options) {
if (options.memoryWarningThreshold) { if (options.memoryWarningThreshold) {
this.memoryWarningThreshold = options.memoryWarningThreshold; this.memoryWarningThreshold = options.memoryWarningThreshold;
}
if (options.maxMetricsHistory) {
this.maxMetricsHistory = options.maxMetricsHistory;
}
if (options.memoryAlertCallback) {
this.memoryAlertCallback = options.memoryAlertCallback;
}
} }
if (options.maxMetricsHistory) { // Override the parent's monitoring with our enhanced version
this.maxMetricsHistory = options.maxMetricsHistory; this.startEnhancedMonitoring();
}
if (options.memoryAlertCallback) {
this.memoryAlertCallback = options.memoryAlertCallback;
}
}
// Override the parent's monitoring with our enhanced version
this.startEnhancedMonitoring();
} }
private startEnhancedMonitoring(): void { private startEnhancedMonitoring(): void {
// Stop any existing monitoring from parent class // Stop any existing monitoring from parent class
if (this.rafHandle) { if (this.rafHandle) {
cancelAnimationFrame(this.rafHandle); cancelAnimationFrame(this.rafHandle);
}
if (this.memoryCheckInterval) {
clearInterval(this.memoryCheckInterval);
}
// Enhanced FPS monitoring with frame time tracking
let lastFrameTime = performance.now();
let frameCount = 0;
let frameTimes: number[] = [];
const measureFPS = () => {
const now = performance.now();
const frameTime = now - lastFrameTime;
lastFrameTime = now;
// Track individual frame times for jank detection
frameTimes.push(frameTime);
if (frameTimes.length > 60) { // Keep only last 60 frame times
frameTimes.shift();
} }
frameCount++; if (this.memoryCheckInterval) {
this.frameTimeHistory.push(frameTime); clearInterval(this.memoryCheckInterval);
// Calculate FPS every second
if (this.frameTimeHistory.length >= 60) {
const totalTime = this.frameTimeHistory.reduce((sum, time) => sum + time, 0);
const fps = Math.round((this.frameTimeHistory.length * 1000) / totalTime);
// Get metrics from parent class
const metrics = this.getMetrics();
metrics.fps.push(fps);
// Limit metrics history
if (metrics.fps.length > this.maxMetricsHistory) {
metrics.fps.shift();
}
// Detect jank (long frames)
const jankThreshold = 16.7 * 2; // 2x normal frame time at 60fps
const jankFrames = frameTimes.filter(time => time > jankThreshold);
if (jankFrames.length > 10) { // If more than 10 out of 60 frames are janky
this.detectPerformanceIssue('jank', {
jankFrames: jankFrames.length,
averageJankTime: jankFrames.reduce((sum, time) => sum + time, 0) / jankFrames.length
});
}
// Reset for next measurement
this.frameTimeHistory = [];
frameTimes = [];
} }
// Enhanced FPS monitoring with frame time tracking
let lastFrameTime = performance.now();
let frameCount = 0;
let frameTimes: number[] = [];
const measureFPS = () => {
const now = performance.now();
const frameTime = now - lastFrameTime;
lastFrameTime = now;
// Track individual frame times for jank detection
frameTimes.push(frameTime);
if (frameTimes.length > 60) { // Keep only last 60 frame times
frameTimes.shift();
}
frameCount++;
this.frameTimeHistory.push(frameTime);
// Calculate FPS every second
if (this.frameTimeHistory.length >= 60) {
const totalTime = this.frameTimeHistory.reduce((sum, time) => sum + time, 0);
const fps = Math.round((this.frameTimeHistory.length * 1000) / totalTime);
// Get metrics from parent class
const metrics = this.getMetrics();
metrics.fps.push(fps);
// Limit metrics history
if (metrics.fps.length > this.maxMetricsHistory) {
metrics.fps.shift();
}
// Detect jank (long frames)
const jankThreshold = 16.7 * 2; // 2x normal frame time at 60fps
const jankFrames = frameTimes.filter(time => time > jankThreshold);
if (jankFrames.length > 10) { // If more than 10 out of 60 frames are janky
this.detectPerformanceIssue('jank', {
jankFrames: jankFrames.length,
averageJankTime: jankFrames.reduce((sum, time) => sum + time, 0) / jankFrames.length
});
}
// Reset for next measurement
this.frameTimeHistory = [];
frameTimes = [];
}
this.rafHandle = requestAnimationFrame(measureFPS);
};
this.rafHandle = requestAnimationFrame(measureFPS); this.rafHandle = requestAnimationFrame(measureFPS);
};
this.rafHandle = requestAnimationFrame(measureFPS); // Enhanced memory monitoring
if (window.performance && (performance as any).memory) {
this.memoryCheckInterval = setInterval(() => {
const memory = (performance as any).memory;
const memoryInfo = {
usedJSHeapSize: memory.usedJSHeapSize,
totalJSHeapSize: memory.totalJSHeapSize,
timestamp: Date.now()
};
// Enhanced memory monitoring // Get metrics from parent class
if (window.performance && (performance as any).memory) { const metrics = this.getMetrics();
this.memoryCheckInterval = setInterval(() => { metrics.memoryUsage.push(memoryInfo);
const memory = (performance as any).memory;
const memoryInfo = {
usedJSHeapSize: memory.usedJSHeapSize,
totalJSHeapSize: memory.totalJSHeapSize,
timestamp: Date.now()
};
// Get metrics from parent class // Limit metrics history
const metrics = this.getMetrics(); if (metrics.memoryUsage.length > this.maxMetricsHistory) {
metrics.memoryUsage.push(memoryInfo); metrics.memoryUsage.shift();
}
// Limit metrics history // Check for memory warnings
if (metrics.memoryUsage.length > this.maxMetricsHistory) { if (memoryInfo.usedJSHeapSize > this.memoryWarningThreshold) {
metrics.memoryUsage.shift(); this.detectPerformanceIssue('memory', memoryInfo);
}
// Check for memory warnings if (this.memoryAlertCallback) {
if (memoryInfo.usedJSHeapSize > this.memoryWarningThreshold) { this.memoryAlertCallback(memoryInfo);
this.detectPerformanceIssue('memory', memoryInfo); }
}
if (this.memoryAlertCallback) { // Check for memory leaks (steady increase)
this.memoryAlertCallback(memoryInfo); if (metrics.memoryUsage.length >= 10) {
} const recentMemory = metrics.memoryUsage.slice(-10);
} let increasingCount = 0;
// Check for memory leaks (steady increase) for (let i = 1; i < recentMemory.length; i++) {
if (metrics.memoryUsage.length >= 10) { if (recentMemory[i].usedJSHeapSize > recentMemory[i - 1].usedJSHeapSize) {
const recentMemory = metrics.memoryUsage.slice(-10); increasingCount++;
let increasingCount = 0; }
}
for (let i = 1; i < recentMemory.length; i++) { // If memory increased in 8 out of 9 consecutive readings
if (recentMemory[i].usedJSHeapSize > recentMemory[i-1].usedJSHeapSize) { if (increasingCount >= 8) {
increasingCount++; this.detectPerformanceIssue('memoryLeak', {
} startMemory: recentMemory[0].usedJSHeapSize,
} currentMemory: recentMemory[recentMemory.length - 1].usedJSHeapSize,
increaseRate: (recentMemory[recentMemory.length - 1].usedJSHeapSize - recentMemory[0].usedJSHeapSize) /
// If memory increased in 8 out of 9 consecutive readings (recentMemory[recentMemory.length - 1].timestamp - recentMemory[0].timestamp) * 1000 // bytes per second
if (increasingCount >= 8) { });
this.detectPerformanceIssue('memoryLeak', { }
startMemory: recentMemory[0].usedJSHeapSize, }
currentMemory: recentMemory[recentMemory.length - 1].usedJSHeapSize, }, 1000);
increaseRate: (recentMemory[recentMemory.length - 1].usedJSHeapSize - recentMemory[0].usedJSHeapSize) / }
(recentMemory[recentMemory.length - 1].timestamp - recentMemory[0].timestamp) * 1000 // bytes per second
});
}
}
}, 1000);
}
} }
// Method to detect various performance issues // Method to detect various performance issues
private detectPerformanceIssue(type: 'jank' | 'memory' | 'memoryLeak', data: any): void { private detectPerformanceIssue(type: 'jank' | 'memory' | 'memoryLeak', data: any): void {
console.warn(`Performance issue detected: ${type}`, data); console.warn(`Performance issue detected: ${type}`, data);
if (type === 'memory' || type === 'memoryLeak') { if (type === 'memory' || type === 'memoryLeak') {
// Auto-throttle rendering if memory issues detected // Auto-throttle rendering if memory issues detected
if (!this.isThrottled) { if (!this.isThrottled) {
this.throttleRendering(); this.throttleRendering();
}
// Suggest garbage collection
this.suggestGarbageCollection();
} }
// Suggest garbage collection
this.suggestGarbageCollection();
}
} }
// Get access to the metrics from parent class // Get access to the metrics from parent class
private getMetrics(): any { private getMetrics(): any {
return (this as any).metrics; return (this as any).metrics;
} }
// Throttle rendering to reduce memory pressure // Throttle rendering to reduce memory pressure
private throttleRendering(): void { private throttleRendering(): void {
this.isThrottled = true; this.isThrottled = true;
console.info('Throttling rendering due to memory pressure'); console.info('Throttling rendering due to memory pressure');
// Application code would implement throttling behavior // Application code would implement throttling behavior
} }
// Un-throttle rendering when memory pressure is reduced // Un-throttle rendering when memory pressure is reduced
public unthrottleRendering(): void { public unthrottleRendering(): void {
if (this.isThrottled) { if (this.isThrottled) {
this.isThrottled = false; this.isThrottled = false;
console.info('Resuming normal rendering'); console.info('Resuming normal rendering');
} }
} }
// Suggest garbage collection to the browser // Suggest garbage collection to the browser
private suggestGarbageCollection(): void { private suggestGarbageCollection(): void {
if (window.gc) { if (window.gc) {
try { try {
window.gc(); window.gc();
} catch (e) { } catch (e) {
// gc() might not be available without special flags // gc() might not be available without special flags
}
} }
}
// Alternative approach to encourage garbage collection // Alternative approach to encourage garbage collection
const largeArray = new Array(1000000).fill(0); const largeArray = new Array(1000000).fill(0);
largeArray.length = 0; largeArray.length = 0;
} }
// Enhanced performance report with more detailed metrics // Enhanced performance report with more detailed metrics
public getEnhancedPerformanceReport(): EnhancedPerformanceReport { public getEnhancedPerformanceReport(): EnhancedPerformanceReport {
const baseReport = super.getPerformanceReport(); const baseReport = super.getPerformanceReport();
const metrics = this.getMetrics(); const metrics = this.getMetrics();
// Calculate 95th percentile render time // Calculate 95th percentile render time
const sortedRenderTimes = [...metrics.renderTime].sort((a, b) => a - b); const sortedRenderTimes = [...metrics.renderTime].sort((a, b) => a - b);
const idx95 = Math.floor(sortedRenderTimes.length * 0.95); const idx95 = Math.floor(sortedRenderTimes.length * 0.95);
const renderTime95Percentile = sortedRenderTimes[idx95] || 0; const renderTime95Percentile = sortedRenderTimes[idx95] || 0;
// Calculate memory growth rate // Calculate memory growth rate
let memoryGrowthRate = 0; let memoryGrowthRate = 0;
if (metrics.memoryUsage.length >= 2) { if (metrics.memoryUsage.length >= 2) {
const first = metrics.memoryUsage[0]; const first = metrics.memoryUsage[0];
const last = metrics.memoryUsage[metrics.memoryUsage.length - 1]; const last = metrics.memoryUsage[metrics.memoryUsage.length - 1];
const timeDiffInSeconds = (last.timestamp - first.timestamp) / 1000; const timeDiffInSeconds = (last.timestamp - first.timestamp) / 1000;
memoryGrowthRate = timeDiffInSeconds > 0 memoryGrowthRate = timeDiffInSeconds > 0
? (last.usedJSHeapSize - first.usedJSHeapSize) / timeDiffInSeconds ? (last.usedJSHeapSize - first.usedJSHeapSize) / timeDiffInSeconds
: 0; : 0;
} }
return { return {
...baseReport, ...baseReport,
renderTime95Percentile, renderTime95Percentile,
memoryGrowthRate, memoryGrowthRate,
isThrottled: this.isThrottled, isThrottled: this.isThrottled,
heapUsagePercentage: baseReport.lastMemoryUsage heapUsagePercentage: baseReport.lastMemoryUsage
? (baseReport.lastMemoryUsage.usedJSHeapSize / baseReport.lastMemoryUsage.totalJSHeapSize) * 100 ? (baseReport.lastMemoryUsage.usedJSHeapSize / baseReport.lastMemoryUsage.totalJSHeapSize) * 100
: 0 : 0
}; };
} }
// Clean up resources when no longer needed // Clean up resources when no longer needed
public dispose(): void { public dispose(): void {
if (this.rafHandle) { if (this.rafHandle) {
cancelAnimationFrame(this.rafHandle); cancelAnimationFrame(this.rafHandle);
this.rafHandle = null; this.rafHandle = null;
} }
if (this.memoryCheckInterval) { if (this.memoryCheckInterval) {
clearInterval(this.memoryCheckInterval); clearInterval(this.memoryCheckInterval);
this.memoryCheckInterval = null; this.memoryCheckInterval = null;
} }
} }
} }
// Extended types // Extended types
interface EnhancedPerformanceReport extends PerformanceReport { interface EnhancedPerformanceReport extends PerformanceReport {
renderTime95Percentile: number; renderTime95Percentile: number;
memoryGrowthRate: number; // bytes per second memoryGrowthRate: number; // bytes per second
isThrottled: boolean; isThrottled: boolean;
heapUsagePercentage: number; heapUsagePercentage: number;
} }
// Backend Performance Monitoring // Backend Performance Monitoring
export class BackendPerformanceMonitor { export class BackendPerformanceMonitor {