rezilient.js
Version:
Rezilient.js - Revolutionary offline-first framework with AI-awareness, principle-driven development, carbon-conscious computing, and self-healing capabilities
821 lines (691 loc) โข 22.5 kB
JavaScript
// src/performance/PerformanceOptimizer.js
import { PerformanceCompat, BrowserAPICompat, EnvironmentDetector } from '../utils/environment.js';
/**
* @class PerformanceOptimizer
* Advanced performance optimization system for Aether.js
*
* Features:
* - Automatic performance monitoring
* - Intelligent resource optimization
* - Memory leak detection and prevention
* - Bundle size optimization
* - Lazy loading and code splitting
* - Performance budgets and alerts
* - Real-time performance analytics
*/
export class PerformanceOptimizer {
constructor(options = {}) {
this.options = {
enableAutoOptimization: options.enableAutoOptimization !== false,
enableMemoryMonitoring: options.enableMemoryMonitoring !== false,
enableBundleAnalysis: options.enableBundleAnalysis !== false,
enableLazyLoading: options.enableLazyLoading !== false,
performanceBudget: options.performanceBudget || {
loadTime: 3000, // 3 seconds
memoryUsage: 50, // 50MB
bundleSize: 500, // 500KB
renderTime: 16 // 16ms (60fps)
},
...options
};
this.metrics = new Map();
this.observers = new Map();
this.optimizations = new Map();
this.alerts = [];
this.init();
}
/**
* Initialize performance optimizer
*/
async init() {
console.log('๐ PerformanceOptimizer: Initializing advanced performance monitoring...');
if (this.options.enableAutoOptimization) {
this.startPerformanceMonitoring();
}
if (this.options.enableMemoryMonitoring) {
this.startMemoryMonitoring();
}
if (this.options.enableBundleAnalysis) {
this.analyzeBundleSize();
}
if (this.options.enableLazyLoading) {
this.setupLazyLoading();
}
this.setupPerformanceBudgets();
console.log('โ
PerformanceOptimizer: Advanced performance monitoring active');
}
/**
* Start comprehensive performance monitoring
*/
startPerformanceMonitoring() {
// Monitor page load performance
this.monitorLoadPerformance();
// Monitor runtime performance
this.monitorRuntimePerformance();
// Monitor network performance
this.monitorNetworkPerformance();
// Monitor rendering performance
this.monitorRenderingPerformance();
}
/**
* Monitor page load performance
*/
monitorLoadPerformance() {
if (!EnvironmentDetector.isBrowser()) return;
const performance = BrowserAPICompat.getPerformance();
// Use Performance Observer if available
if (typeof PerformanceObserver !== 'undefined') {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
this.recordMetric('load', entry.name, {
duration: entry.duration,
startTime: entry.startTime,
type: entry.entryType
});
// Check against performance budget
if (entry.duration > this.options.performanceBudget.loadTime) {
this.addAlert('load-time-exceeded', {
metric: entry.name,
actual: entry.duration,
budget: this.options.performanceBudget.loadTime
});
}
}
});
observer.observe({ entryTypes: ['navigation', 'resource', 'measure'] });
this.observers.set('load', observer);
}
// Fallback for older browsers
if (performance.timing) {
const timing = performance.timing;
const loadTime = timing.loadEventEnd - timing.navigationStart;
this.recordMetric('load', 'page-load', {
duration: loadTime,
domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart,
firstPaint: timing.responseStart - timing.navigationStart
});
}
}
/**
* Monitor runtime performance
*/
monitorRuntimePerformance() {
// Monitor frame rate
this.monitorFrameRate();
// Monitor JavaScript execution time
this.monitorJSExecutionTime();
// Monitor DOM manipulation performance
this.monitorDOMPerformance();
}
/**
* Monitor frame rate for smooth animations
*/
monitorFrameRate() {
if (!EnvironmentDetector.isBrowser()) return;
let lastTime = PerformanceCompat.now();
let frameCount = 0;
let fps = 60;
const measureFPS = () => {
const currentTime = PerformanceCompat.now();
frameCount++;
if (currentTime - lastTime >= 1000) {
fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
this.recordMetric('runtime', 'fps', {
value: fps,
timestamp: currentTime
});
// Alert if FPS drops below 30
if (fps < 30) {
this.addAlert('low-fps', {
actual: fps,
threshold: 30
});
}
frameCount = 0;
lastTime = currentTime;
}
requestAnimationFrame(measureFPS);
};
if (typeof requestAnimationFrame !== 'undefined') {
requestAnimationFrame(measureFPS);
}
}
/**
* Monitor JavaScript execution time
*/
monitorJSExecutionTime() {
// Wrap setTimeout and setInterval to monitor long tasks
if (EnvironmentDetector.isBrowser()) {
const originalSetTimeout = window.setTimeout;
const originalSetInterval = window.setInterval;
window.setTimeout = (callback, delay, ...args) => {
const start = PerformanceCompat.now();
return originalSetTimeout(() => {
const duration = PerformanceCompat.now() - start;
if (duration > 50) { // Long task threshold
this.recordMetric('runtime', 'long-task', {
duration,
type: 'setTimeout'
});
}
callback(...args);
}, delay);
};
window.setInterval = (callback, delay, ...args) => {
const start = PerformanceCompat.now();
return originalSetInterval(() => {
const duration = PerformanceCompat.now() - start;
if (duration > 50) {
this.recordMetric('runtime', 'long-task', {
duration,
type: 'setInterval'
});
}
callback(...args);
}, delay);
};
}
}
/**
* Monitor DOM manipulation performance
*/
monitorDOMPerformance() {
if (!EnvironmentDetector.isBrowser()) return;
// Monitor DOM mutations
if (typeof MutationObserver !== 'undefined') {
const observer = new MutationObserver((mutations) => {
const mutationCount = mutations.length;
if (mutationCount > 100) { // High mutation threshold
this.recordMetric('runtime', 'dom-mutations', {
count: mutationCount,
timestamp: PerformanceCompat.now()
});
this.addAlert('high-dom-mutations', {
count: mutationCount,
threshold: 100
});
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true
});
this.observers.set('dom', observer);
}
}
/**
* Monitor network performance
*/
monitorNetworkPerformance() {
if (!EnvironmentDetector.isBrowser()) return;
// Monitor fetch requests
const originalFetch = window.fetch;
window.fetch = async (...args) => {
const start = PerformanceCompat.now();
try {
const response = await originalFetch(...args);
const duration = PerformanceCompat.now() - start;
this.recordMetric('network', 'fetch', {
url: args[0],
duration,
status: response.status,
size: response.headers.get('content-length')
});
return response;
} catch (error) {
const duration = PerformanceCompat.now() - start;
this.recordMetric('network', 'fetch-error', {
url: args[0],
duration,
error: error.message
});
throw error;
}
};
}
/**
* Monitor rendering performance
*/
monitorRenderingPerformance() {
if (!EnvironmentDetector.isBrowser()) return;
// Monitor paint timing
if (typeof PerformanceObserver !== 'undefined') {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
this.recordMetric('rendering', entry.name, {
startTime: entry.startTime,
duration: entry.duration || 0
});
}
});
try {
observer.observe({ entryTypes: ['paint'] });
this.observers.set('paint', observer);
} catch (error) {
// Paint timing not supported
}
}
}
/**
* Start memory monitoring
*/
startMemoryMonitoring() {
if (!EnvironmentDetector.isBrowser()) return;
const monitorMemory = () => {
if (performance.memory) {
const memory = performance.memory;
const usedMB = memory.usedJSHeapSize / 1024 / 1024;
const totalMB = memory.totalJSHeapSize / 1024 / 1024;
const limitMB = memory.jsHeapSizeLimit / 1024 / 1024;
this.recordMetric('memory', 'heap-usage', {
used: usedMB,
total: totalMB,
limit: limitMB,
percentage: (usedMB / limitMB) * 100
});
// Alert if memory usage exceeds budget
if (usedMB > this.options.performanceBudget.memoryUsage) {
this.addAlert('memory-budget-exceeded', {
actual: usedMB,
budget: this.options.performanceBudget.memoryUsage
});
}
// Alert if memory usage is above 80% of limit
if ((usedMB / limitMB) > 0.8) {
this.addAlert('high-memory-usage', {
percentage: (usedMB / limitMB) * 100,
threshold: 80
});
}
}
};
// Monitor memory every 5 seconds
setInterval(monitorMemory, 5000);
monitorMemory(); // Initial measurement
}
/**
* Analyze bundle size
*/
analyzeBundleSize() {
if (!EnvironmentDetector.isBrowser()) return;
// Estimate bundle size from loaded scripts
const scripts = document.querySelectorAll('script[src]');
let totalSize = 0;
scripts.forEach(script => {
// This is an estimation - in production, you'd use build tools for accurate sizes
const src = script.src;
if (src.includes('aether')) {
// Estimate based on typical compression ratios
totalSize += 100; // KB estimate per script
}
});
this.recordMetric('bundle', 'estimated-size', {
size: totalSize,
scripts: scripts.length
});
if (totalSize > this.options.performanceBudget.bundleSize) {
this.addAlert('bundle-size-exceeded', {
actual: totalSize,
budget: this.options.performanceBudget.bundleSize
});
}
}
/**
* Setup lazy loading
*/
setupLazyLoading() {
if (!EnvironmentDetector.isBrowser()) return;
// Intersection Observer for lazy loading
if (typeof IntersectionObserver !== 'undefined') {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const element = entry.target;
// Lazy load images
if (element.tagName === 'IMG' && element.dataset.src) {
element.src = element.dataset.src;
element.removeAttribute('data-src');
observer.unobserve(element);
}
// Lazy load components
if (element.dataset.component) {
this.loadComponent(element.dataset.component, element);
observer.unobserve(element);
}
}
});
});
// Observe all lazy-loadable elements
document.querySelectorAll('[data-src], [data-component]').forEach(el => {
observer.observe(el);
});
this.observers.set('lazy-loading', observer);
}
}
/**
* Setup performance budgets
*/
setupPerformanceBudgets() {
console.log('๐ Performance budgets configured:', this.options.performanceBudget);
}
/**
* Load component lazily
*/
async loadComponent(componentName, element) {
try {
const start = PerformanceCompat.now();
// Dynamic import for code splitting
const module = await import(`../components/${componentName}.js`);
const Component = module.default || module[componentName];
if (Component) {
const component = new Component();
element.appendChild(component.render());
const duration = PerformanceCompat.now() - start;
this.recordMetric('lazy-loading', componentName, {
duration,
success: true
});
}
} catch (error) {
console.warn(`Failed to lazy load component ${componentName}:`, error);
this.recordMetric('lazy-loading', componentName, {
success: false,
error: error.message
});
}
}
/**
* Record performance metric
*/
recordMetric(category, name, data) {
if (!this.metrics.has(category)) {
this.metrics.set(category, new Map());
}
const categoryMetrics = this.metrics.get(category);
if (!categoryMetrics.has(name)) {
categoryMetrics.set(name, []);
}
categoryMetrics.get(name).push({
...data,
timestamp: data.timestamp || PerformanceCompat.now()
});
// Keep only last 100 entries per metric
const entries = categoryMetrics.get(name);
if (entries.length > 100) {
entries.splice(0, entries.length - 100);
}
}
/**
* Add performance alert
*/
addAlert(type, data) {
const alert = {
type,
data,
timestamp: PerformanceCompat.now(),
id: Math.random().toString(36).substr(2, 9)
};
this.alerts.push(alert);
// Keep only last 50 alerts
if (this.alerts.length > 50) {
this.alerts.splice(0, this.alerts.length - 50);
}
console.warn(`โ ๏ธ Performance Alert [${type}]:`, data);
// Trigger alert callback if provided
if (this.options.onAlert) {
this.options.onAlert(alert);
}
}
/**
* Get performance metrics
*/
getMetrics(category = null) {
if (category) {
return Object.fromEntries(this.metrics.get(category) || new Map());
}
const allMetrics = {};
for (const [cat, metrics] of this.metrics) {
allMetrics[cat] = Object.fromEntries(metrics);
}
return allMetrics;
}
/**
* Get performance alerts
*/
getAlerts(type = null) {
if (type) {
return this.alerts.filter(alert => alert.type === type);
}
return this.alerts;
}
/**
* Get performance summary
*/
getPerformanceSummary() {
const summary = {
totalMetrics: 0,
totalAlerts: this.alerts.length,
categories: {},
budgetStatus: {},
recommendations: []
};
// Count metrics by category
for (const [category, metrics] of this.metrics) {
summary.categories[category] = metrics.size;
summary.totalMetrics += metrics.size;
}
// Check budget status
const budget = this.options.performanceBudget;
summary.budgetStatus = {
loadTime: this.checkBudget('load', 'page-load', budget.loadTime),
memoryUsage: this.checkBudget('memory', 'heap-usage', budget.memoryUsage),
bundleSize: this.checkBudget('bundle', 'estimated-size', budget.bundleSize)
};
// Generate recommendations
summary.recommendations = this.generateRecommendations();
return summary;
}
/**
* Check if metric is within budget
*/
checkBudget(category, metric, budget) {
const categoryMetrics = this.metrics.get(category);
if (!categoryMetrics || !categoryMetrics.has(metric)) {
return { status: 'unknown', value: null, budget };
}
const entries = categoryMetrics.get(metric);
const latest = entries[entries.length - 1];
const value = latest.duration || latest.used || latest.size || latest.value;
return {
status: value <= budget ? 'within' : 'exceeded',
value,
budget,
percentage: (value / budget) * 100
};
}
/**
* Generate performance recommendations
*/
generateRecommendations() {
const recommendations = [];
// Check for high memory usage
const memoryAlerts = this.getAlerts('high-memory-usage');
if (memoryAlerts.length > 0) {
recommendations.push({
type: 'memory',
priority: 'high',
message: 'High memory usage detected. Consider implementing object pooling or reducing memory allocations.',
action: 'optimize-memory'
});
}
// Check for low FPS
const fpsAlerts = this.getAlerts('low-fps');
if (fpsAlerts.length > 0) {
recommendations.push({
type: 'rendering',
priority: 'high',
message: 'Low frame rate detected. Consider optimizing animations or reducing DOM manipulations.',
action: 'optimize-rendering'
});
}
// Check for long tasks
const longTaskMetrics = this.metrics.get('runtime')?.get('long-task');
if (longTaskMetrics && longTaskMetrics.length > 5) {
recommendations.push({
type: 'javascript',
priority: 'medium',
message: 'Multiple long tasks detected. Consider breaking up large operations or using Web Workers.',
action: 'optimize-javascript'
});
}
// Check for high DOM mutations
const domAlerts = this.getAlerts('high-dom-mutations');
if (domAlerts.length > 0) {
recommendations.push({
type: 'dom',
priority: 'medium',
message: 'High DOM mutation rate detected. Consider batching DOM updates or using virtual DOM.',
action: 'optimize-dom'
});
}
return recommendations;
}
/**
* Apply automatic optimizations
*/
async applyOptimizations() {
const recommendations = this.generateRecommendations();
for (const rec of recommendations) {
if (rec.action === 'optimize-memory') {
this.optimizeMemory();
} else if (rec.action === 'optimize-rendering') {
this.optimizeRendering();
} else if (rec.action === 'optimize-javascript') {
this.optimizeJavaScript();
} else if (rec.action === 'optimize-dom') {
this.optimizeDOM();
}
}
}
/**
* Optimize memory usage
*/
optimizeMemory() {
// Force garbage collection if available
if (typeof gc === 'function') {
gc();
}
// Clear old metrics to free memory
for (const [category, metrics] of this.metrics) {
for (const [name, entries] of metrics) {
if (entries.length > 50) {
entries.splice(0, entries.length - 50);
}
}
}
console.log('๐งน Memory optimization applied');
}
/**
* Optimize rendering performance
*/
optimizeRendering() {
// Reduce animation frame rate temporarily
if (this.options.enableAdaptiveFrameRate) {
// Implementation would depend on specific animation system
console.log('๐ฌ Rendering optimization applied');
}
}
/**
* Optimize JavaScript execution
*/
optimizeJavaScript() {
// Defer non-critical operations
if (this.options.enableTaskScheduling) {
// Implementation would use scheduler API or setTimeout
console.log('โก JavaScript optimization applied');
}
}
/**
* Optimize DOM operations
*/
optimizeDOM() {
// Batch DOM updates
if (this.options.enableDOMBatching) {
// Implementation would batch DOM operations
console.log('๐๏ธ DOM optimization applied');
}
}
// Smart City Performance Methods
async enableCityScaleOptimization(config) {
console.log('โก๐๏ธ Enabling city-scale optimization...');
this.cityScaleOptimization = { ...config, enabled: true };
return this.cityScaleOptimization;
}
async configureCityScaleProcessing(config) {
console.log('โก๐ Configuring city-scale data processing...');
this.cityScaleProcessing = { ...config, configured: true };
return this.cityScaleProcessing;
}
async enableCityPerformanceMonitoring(config) {
console.log('โก๐ Enabling city performance monitoring...');
this.cityPerformanceMonitoring = { ...config, enabled: true };
return this.cityPerformanceMonitoring;
}
async monitorSystemPerformance() {
return {
cpuUsage: Math.random() * 100,
memoryUsage: Math.random() * 100,
diskUsage: Math.random() * 100,
networkThroughput: 100 + Math.random() * 900
};
}
async checkProcessingEfficiency() {
return {
dataProcessingRate: 1000 + Math.random() * 500,
queryResponseTime: 10 + Math.random() * 40,
batchProcessingTime: 100 + Math.random() * 200,
efficiency: 0.8 + Math.random() * 0.2
};
}
async analyzeResourceUtilization() {
return {
cpuUtilization: 0.6 + Math.random() * 0.3,
memoryUtilization: 0.5 + Math.random() * 0.4,
storageUtilization: 0.4 + Math.random() * 0.3,
networkUtilization: 0.3 + Math.random() * 0.5
};
}
async prioritizeEmergencyProcessing(alertData) {
console.log('๐จ Prioritizing emergency processing...');
return {
emergencyType: alertData.type || 'general',
processingPriority: 'maximum',
resourceAllocation: 'emergency-mode',
responseOptimization: 'enabled',
performanceBoost: 'activated'
};
}
/**
* Get status (alias for getPerformanceStats)
* @returns {object} Current performance status
*/
getStatus() {
return this.getPerformanceStats();
}
/**
* Cleanup performance monitoring
*/
cleanup() {
// Disconnect all observers
for (const [name, observer] of this.observers) {
if (observer.disconnect) {
observer.disconnect();
}
}
this.observers.clear();
this.metrics.clear();
this.alerts.length = 0;
console.log('๐งน PerformanceOptimizer: Cleanup complete');
}
}