UNPKG

@stacksleuth/performance-optimizer

Version:

Intelligent performance optimization engine - Automated bottleneck detection, code optimization suggestions, resource optimization, and performance enhancement recommendations.

507 lines 20.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.performanceOptimizerAgent = exports.PerformanceOptimizerAgent = void 0; const core_1 = require("@stacksleuth/core"); class PerformanceOptimizerAgent { constructor(config) { this.isActive = false; this.metrics = new Map(); this.baselines = new Map(); this.issues = new Map(); this.recommendations = new Map(); this.profiler = new core_1.ProfilerCore(config); this.config = { analysisInterval: config?.analysisInterval || 30000, // 30 seconds maxMetricHistory: config?.maxMetricHistory || 1000, baselineSamples: config?.baselineSamples || 100, enableAutoOptimization: config?.enableAutoOptimization || false, thresholds: { 'response_time': 1000, 'database_query_time': 500, 'memory_usage': 85, 'cpu_usage': 80, 'error_rate': 5, 'network_latency': 200, ...config?.customThresholds } }; } /** * Initialize the performance optimizer */ async init() { if (this.isActive) return; this.isActive = true; await this.profiler.init(); // Start periodic analysis this.analysisInterval = setInterval(() => { this.runAnalysis(); }, this.config.analysisInterval); console.log('✅ Performance Optimizer Agent initialized'); } /** * Record a performance metric */ recordMetric(metric) { if (!this.isActive) return; const key = `${metric.component}:${metric.metric}`; const metrics = this.metrics.get(key) || []; metrics.push(metric); // Keep only recent metrics if (metrics.length > this.config.maxMetricHistory) { metrics.shift(); } this.metrics.set(key, metrics); // Update baseline if needed this.updateBaseline(metric); // Record with profiler this.profiler.recordMetric('performance_metric', { ...metric, timestamp: Date.now() }); } /** * Update performance baseline */ updateBaseline(metric) { const key = `${metric.component}:${metric.metric}`; const existing = this.baselines.get(key); if (!existing) { // Create new baseline this.baselines.set(key, { component: metric.component, metric: metric.metric, baseline: metric.value, target: metric.target || metric.value * 0.8, // 20% improvement target threshold: metric.threshold || this.config.thresholds[metric.metric] || metric.value * 1.5, samples: 1, created: Date.now(), updated: Date.now() }); } else { // Update existing baseline with moving average const alpha = 0.1; // Smoothing factor existing.baseline = existing.baseline * (1 - alpha) + metric.value * alpha; existing.samples++; existing.updated = Date.now(); } } /** * Run comprehensive performance analysis */ async runAnalysis() { if (!this.isActive) return; try { // Detect performance issues this.detectIssues(); // Generate optimization recommendations this.generateRecommendations(); // Update trends this.updateTrends(); // Auto-optimize if enabled if (this.config.enableAutoOptimization) { this.applyAutoOptimizations(); } // Record analysis cycle this.profiler.recordMetric('optimization_analysis', { issuesDetected: this.issues.size, recommendationsGenerated: this.recommendations.size, metricsAnalyzed: this.metrics.size, timestamp: Date.now() }); } catch (error) { console.error('Error during performance analysis:', error); } } /** * Detect performance issues */ detectIssues() { for (const [key, metrics] of this.metrics.entries()) { const [component, metric] = key.split(':'); const baseline = this.baselines.get(key); if (!baseline || metrics.length < 10) continue; const recentMetrics = metrics.slice(-10); const average = recentMetrics.reduce((sum, m) => sum + m.value, 0) / recentMetrics.length; // Check if current performance exceeds threshold if (average > baseline.threshold) { const issueId = `${component}_${metric}_${Date.now()}`; const existing = Array.from(this.issues.values()) .find(issue => issue.component === component && issue.metric === metric); if (existing) { // Update existing issue existing.lastDetected = Date.now(); existing.frequency++; existing.currentValue = average; existing.trend = this.calculateTrend(metrics); } else { // Create new issue this.issues.set(issueId, { id: issueId, severity: this.calculateSeverity(average, baseline.threshold, baseline.baseline), component, metric, currentValue: average, expectedValue: baseline.baseline, impact: this.calculateImpact(component, metric, average, baseline.baseline), firstDetected: Date.now(), lastDetected: Date.now(), frequency: 1, trend: this.calculateTrend(metrics) }); } } } } /** * Generate optimization recommendations */ generateRecommendations() { for (const issue of this.issues.values()) { const existingRec = Array.from(this.recommendations.values()) .find(rec => rec.relatedMetrics.includes(`${issue.component}:${issue.metric}`)); if (existingRec) continue; // Already have recommendation for this issue const recommendation = this.createRecommendation(issue); if (recommendation) { this.recommendations.set(recommendation.id, recommendation); } } } /** * Create optimization recommendation based on issue */ createRecommendation(issue) { const templates = this.getRecommendationTemplates(); const key = `${issue.component}_${issue.metric}`; const template = templates[key]; if (!template) return null; return { id: `rec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, priority: issue.severity === 'critical' ? 'high' : issue.severity === 'high' ? 'medium' : 'low', category: this.getCategoryFromComponent(issue.component), title: template.title, description: template.description.replace('{value}', issue.currentValue.toString()), impact: issue.severity === 'critical' ? 'high' : 'medium', effort: template.effort, estimatedImprovement: template.estimatedImprovement, actionItems: template.actionItems, codeExamples: template.codeExamples, relatedMetrics: [`${issue.component}:${issue.metric}`], created: Date.now(), applied: false }; } /** * Get recommendation templates */ getRecommendationTemplates() { return { 'database_query_time': { title: 'Optimize Database Query Performance', description: 'Database queries are taking {value}ms on average, which exceeds the recommended threshold.', effort: 'medium', estimatedImprovement: '30-50% query time reduction', actionItems: [ 'Add database indexes for frequently queried columns', 'Optimize query structure and eliminate N+1 queries', 'Implement query result caching', 'Consider database connection pooling' ], codeExamples: [ '// Add database index\nCREATE INDEX idx_user_email ON users(email);', '// Use eager loading to prevent N+1\nUser.findAll({ include: [{ model: Profile }] })' ] }, 'frontend_render_time': { title: 'Optimize Frontend Rendering Performance', description: 'Component rendering is taking {value}ms, causing UI lag.', effort: 'medium', estimatedImprovement: '40-60% render time reduction', actionItems: [ 'Implement React.memo or useMemo for expensive computations', 'Virtualize long lists and tables', 'Lazy load components and images', 'Optimize bundle size and split code' ], codeExamples: [ '// Memoize expensive component\nconst ExpensiveComponent = React.memo(({ data }) => { ... });', '// Lazy load component\nconst LazyComponent = lazy(() => import(\'./Component\'));' ] }, 'memory_usage': { title: 'Reduce Memory Usage', description: 'Memory usage is at {value}%, approaching critical levels.', effort: 'high', estimatedImprovement: '20-40% memory reduction', actionItems: [ 'Implement memory leak detection and cleanup', 'Optimize data structures and algorithms', 'Add garbage collection tuning', 'Review and optimize caching strategies' ], codeExamples: [ '// Clean up event listeners\nuseEffect(() => { return () => cleanup(); }, []);', '// Optimize data structure\nconst cache = new Map(); // Use Map instead of Object for frequent additions/deletions' ] }, 'network_latency': { title: 'Optimize Network Performance', description: 'Network requests are experiencing {value}ms latency.', effort: 'low', estimatedImprovement: '30-50% latency reduction', actionItems: [ 'Implement request caching and compression', 'Use CDN for static assets', 'Optimize API payload sizes', 'Implement request batching' ], codeExamples: [ '// Enable compression\napp.use(compression());', '// Batch API requests\nconst batchedRequests = Promise.all([req1, req2, req3]);' ] } }; } /** * Update performance trends */ updateTrends() { for (const [key, metrics] of this.metrics.entries()) { if (metrics.length < 20) continue; const recent = metrics.slice(-10); const older = metrics.slice(-20, -10); const recentAvg = recent.reduce((sum, m) => sum + m.value, 0) / recent.length; const olderAvg = older.reduce((sum, m) => sum + m.value, 0) / older.length; const change = (recentAvg - olderAvg) / olderAvg; // Update baseline with trend const baseline = this.baselines.get(key); if (baseline) { if (change < -0.1) { // Improving } else if (change > 0.1) { // Degrading - may need intervention } } } } /** * Apply automatic optimizations */ applyAutoOptimizations() { for (const recommendation of this.recommendations.values()) { if (recommendation.applied || recommendation.effort === 'high') continue; // Only apply low-effort, high-impact optimizations automatically if (recommendation.effort === 'low' && recommendation.impact === 'high') { this.applyRecommendation(recommendation.id); } } } /** * Apply a specific recommendation */ applyRecommendation(recommendationId) { const recommendation = this.recommendations.get(recommendationId); if (!recommendation || recommendation.applied) return false; try { // This would implement the actual optimization // For now, we'll just mark it as applied recommendation.applied = true; this.profiler.recordMetric('optimization_applied', { recommendationId, category: recommendation.category, priority: recommendation.priority, timestamp: Date.now() }); console.log(`✅ Applied optimization: ${recommendation.title}`); return true; } catch (error) { console.error(`Failed to apply optimization ${recommendationId}:`, error); return false; } } /** * Generate comprehensive performance report */ generateReport(timeRange) { const now = Date.now(); const range = timeRange || { start: now - (24 * 60 * 60 * 1000), // Last 24 hours end: now }; const filteredIssues = Array.from(this.issues.values()) .filter(issue => issue.firstDetected >= range.start && issue.firstDetected <= range.end); const filteredRecommendations = Array.from(this.recommendations.values()) .filter(rec => rec.created >= range.start && rec.created <= range.end); const criticalIssues = filteredIssues.filter(issue => issue.severity === 'critical').length; return { id: `report_${Date.now()}`, generated: now, timeRange: range, summary: { totalIssues: filteredIssues.length, criticalIssues, recommendations: filteredRecommendations.length, potentialImprovement: this.calculatePotentialImprovement(filteredRecommendations) }, issues: filteredIssues, recommendations: filteredRecommendations, baselines: Array.from(this.baselines.values()), trends: this.getCurrentTrends() }; } /** * Get current metrics summary */ getMetricsSummary() { const summary = {}; for (const [key, metrics] of this.metrics.entries()) { const [component, metric] = key.split(':'); const recent = metrics.slice(-10); const average = recent.reduce((sum, m) => sum + m.value, 0) / recent.length; const baseline = this.baselines.get(key); if (!summary[component]) { summary[component] = {}; } summary[component][metric] = { current: average, baseline: baseline?.baseline, threshold: baseline?.threshold, trend: this.calculateTrend(metrics), samples: metrics.length }; } return summary; } /** * Get active issues */ getActiveIssues() { return Array.from(this.issues.values()) .filter(issue => Date.now() - issue.lastDetected < 300000) // Active in last 5 minutes .sort((a, b) => { const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 }; return severityOrder[b.severity] - severityOrder[a.severity]; }); } /** * Get pending recommendations */ getPendingRecommendations() { return Array.from(this.recommendations.values()) .filter(rec => !rec.applied) .sort((a, b) => { const priorityOrder = { high: 3, medium: 2, low: 1 }; return priorityOrder[b.priority] - priorityOrder[a.priority]; }); } /** * Helper methods */ calculateSeverity(current, threshold, baseline) { const deviation = (current - baseline) / baseline; if (deviation > 2.0) return 'critical'; if (deviation > 1.0) return 'high'; if (deviation > 0.5) return 'medium'; return 'low'; } calculateImpact(component, metric, current, baseline) { const deviation = ((current - baseline) / baseline * 100).toFixed(1); return `${deviation}% performance degradation in ${component} ${metric}`; } calculateTrend(metrics) { if (metrics.length < 10) return 'stable'; const recent = metrics.slice(-5); const older = metrics.slice(-10, -5); const recentAvg = recent.reduce((sum, m) => sum + m.value, 0) / recent.length; const olderAvg = older.reduce((sum, m) => sum + m.value, 0) / older.length; const change = (recentAvg - olderAvg) / olderAvg; if (change < -0.05) return 'improving'; if (change > 0.05) return 'degrading'; return 'stable'; } getCategoryFromComponent(component) { const categoryMap = { 'database': 'database', 'frontend': 'frontend', 'backend': 'backend', 'network': 'network', 'memory': 'memory', 'cache': 'caching' }; return categoryMap[component] || 'backend'; } calculatePotentialImprovement(recommendations) { const highImpact = recommendations.filter(r => r.impact === 'high').length; const mediumImpact = recommendations.filter(r => r.impact === 'medium').length; const estimated = highImpact * 30 + mediumImpact * 15; return `${estimated}% performance improvement potential`; } getCurrentTrends() { const trends = {}; for (const [key, metrics] of this.metrics.entries()) { trends[key] = this.calculateTrend(metrics); } return trends; } /** * Export optimization data */ exportData() { return { metrics: Object.fromEntries(this.metrics), baselines: Object.fromEntries(this.baselines), issues: Object.fromEntries(this.issues), recommendations: Object.fromEntries(this.recommendations), summary: this.getMetricsSummary() }; } /** * Stop the performance optimizer */ async stop() { if (!this.isActive) return; this.isActive = false; // Clear analysis interval if (this.analysisInterval) { clearInterval(this.analysisInterval); } // Record final analysis this.profiler.recordMetric('optimizer_stopped', { totalMetrics: this.metrics.size, totalIssues: this.issues.size, totalRecommendations: this.recommendations.size, timestamp: Date.now() }); await this.profiler.stop(); console.log('🛑 Performance Optimizer Agent stopped'); } } exports.PerformanceOptimizerAgent = PerformanceOptimizerAgent; // Export default instance exports.performanceOptimizerAgent = new PerformanceOptimizerAgent(); // Auto-initialize if (typeof process !== 'undefined') { exports.performanceOptimizerAgent.init().catch(console.error); } //# sourceMappingURL=index.js.map