UNPKG

xypriss-security

Version:

XyPriss Security is an advanced JavaScript security library designed for enterprise applications. It provides military-grade encryption, secure data structures, quantum-resistant cryptography, and comprehensive security utilities for modern web applicatio

336 lines (332 loc) 12.2 kB
'use strict'; var perf_hooks = require('perf_hooks'); /** * Performance Monitor Module * Provides performance monitoring and optimization for SecureString operations */ /** * Performance metrics for operations */ /** * Performance monitor for SecureString operations */ class PerformanceMonitor { /** * Starts performance monitoring */ static startMonitoring() { this.isMonitoring = true; this.metrics = []; } /** * Stops performance monitoring */ static stopMonitoring() { this.isMonitoring = false; } /** * Records a performance metric */ static recordMetric(operationType, startTime, endTime, operationSize = 0, memoryBefore = 0, memoryAfter = 0) { if (!this.isMonitoring) return; const duration = endTime - startTime; const memoryDelta = memoryAfter - memoryBefore; const throughput = operationSize > 0 ? operationSize / duration : 0; const metric = { operationType, startTime, endTime, duration, memoryBefore, memoryAfter, memoryDelta, operationSize, throughput, }; this.metrics.push(metric); // Keep only recent metrics if (this.metrics.length > this.maxMetricsHistory) { this.metrics = this.metrics.slice(-this.maxMetricsHistory); } } /** * Gets performance statistics */ static getStats() { if (this.metrics.length === 0) { return this.getEmptyStats(); } const durations = this.metrics.map((m) => m.duration); const memoryUsages = this.metrics.map((m) => Math.abs(m.memoryDelta)); const throughputs = this.metrics .map((m) => m.throughput) .filter((t) => t > 0); const operationBreakdown = {}; for (const metric of this.metrics) { operationBreakdown[metric.operationType] = (operationBreakdown[metric.operationType] || 0) + 1; } const averageDuration = durations.reduce((a, b) => a + b, 0) / durations.length; const averageMemoryUsage = memoryUsages.reduce((a, b) => a + b, 0) / memoryUsages.length; const averageThroughput = throughputs.length > 0 ? throughputs.reduce((a, b) => a + b, 0) / throughputs.length : 0; return { totalOperations: this.metrics.length, averageDuration, minDuration: Math.min(...durations), maxDuration: Math.max(...durations), totalMemoryUsed: memoryUsages.reduce((a, b) => a + b, 0), averageMemoryUsage, operationBreakdown, throughputStats: { average: averageThroughput, peak: throughputs.length > 0 ? Math.max(...throughputs) : 0, current: throughputs.length > 0 ? throughputs[throughputs.length - 1] : 0, }, recommendations: this.generateRecommendations(averageDuration, averageMemoryUsage, operationBreakdown, this.metrics.length), }; } /** * Benchmarks a specific operation */ static async benchmark(operation, operationName, iterations = 100, warmupIterations = 10) { // Warmup for (let i = 0; i < warmupIterations; i++) { await operation(); } // Benchmark const times = []; const memoryUsages = []; for (let i = 0; i < iterations; i++) { const memoryBefore = this.getMemoryUsage(); const perf = typeof performance !== "undefined" ? performance : perf_hooks.performance; const startTime = perf.now(); await operation(); const endTime = performance.now(); const memoryAfter = this.getMemoryUsage(); times.push(endTime - startTime); memoryUsages.push(memoryAfter - memoryBefore); } const totalTime = times.reduce((a, b) => a + b, 0); const averageTime = totalTime / iterations; const operationsPerSecond = 1000 / averageTime; memoryUsages.reduce((a, b) => a + b, 0) / iterations; // Calculate efficiency metrics const memoryEfficiency = this.calculateMemoryEfficiency(memoryUsages); const scalabilityScore = this.calculateScalabilityScore(times); return { operation: operationName, iterations, totalTime, averageTime, operationsPerSecond, memoryEfficiency, scalabilityScore, recommendations: this.generateBenchmarkRecommendations(averageTime, memoryEfficiency, scalabilityScore), }; } /** * Profiles memory usage during operation */ static async profileMemory(operation, samplingInterval = 10) { const memoryProfile = []; let isRunning = true; // Start memory sampling const samplingPromise = (async () => { while (isRunning) { memoryProfile.push({ timestamp: Date.now(), usage: this.getMemoryUsage(), }); await this.sleep(samplingInterval); } })(); // Execute operation const result = await operation(); isRunning = false; await samplingPromise; const usages = memoryProfile.map((p) => p.usage); const peakUsage = Math.max(...usages); const averageUsage = usages.reduce((a, b) => a + b, 0) / usages.length; return { result, memoryProfile, peakUsage, averageUsage, }; } /** * Measures operation with automatic metric recording */ static async measure(operation, operationType, operationSize = 0) { const memoryBefore = this.getMemoryUsage(); const startTime = performance.now(); try { const result = await operation(); const endTime = performance.now(); const memoryAfter = this.getMemoryUsage(); this.recordMetric(operationType, startTime, endTime, operationSize, memoryBefore, memoryAfter); return result; } catch (error) { const endTime = performance.now(); const memoryAfter = this.getMemoryUsage(); this.recordMetric(`${operationType}_ERROR`, startTime, endTime, operationSize, memoryBefore, memoryAfter); throw error; } } /** * Gets recent metrics for a specific operation type */ static getMetricsForOperation(operationType, limit = 50) { return this.metrics .filter((m) => m.operationType === operationType) .slice(-limit); } /** * Clears all metrics */ static clearMetrics() { this.metrics = []; } /** * Exports metrics to JSON */ static exportMetrics() { return JSON.stringify({ timestamp: new Date().toISOString(), metrics: this.metrics, stats: this.getStats(), }, null, 2); } /** * Analyzes performance trends */ static analyzeTrends(operationType) { const relevantMetrics = operationType ? this.metrics.filter((m) => m.operationType === operationType) : this.metrics; if (relevantMetrics.length < 10) { return { trend: "stable", confidence: 0, analysis: "Insufficient data for trend analysis", }; } // Analyze last 20% vs first 20% of metrics const sampleSize = Math.floor(relevantMetrics.length * 0.2); const earlyMetrics = relevantMetrics.slice(0, sampleSize); const recentMetrics = relevantMetrics.slice(-sampleSize); const earlyAvg = earlyMetrics.reduce((sum, m) => sum + m.duration, 0) / earlyMetrics.length; const recentAvg = recentMetrics.reduce((sum, m) => sum + m.duration, 0) / recentMetrics.length; const change = (recentAvg - earlyAvg) / earlyAvg; const confidence = Math.min(1, sampleSize / 10); let trend; let analysis; if (Math.abs(change) < 0.05) { trend = "stable"; analysis = "Performance has remained relatively stable"; } else if (change < 0) { trend = "improving"; analysis = `Performance has improved by ${Math.abs(change * 100).toFixed(1)}%`; } else { trend = "degrading"; analysis = `Performance has degraded by ${Math.abs(change * 100).toFixed(1)}%`; } return { trend, confidence, analysis }; } /** * Helper methods */ static getMemoryUsage() { if (typeof performance !== "undefined" && "memory" in performance) { return performance.memory?.usedJSHeapSize ?? 0; } if (typeof process !== "undefined" && process.memoryUsage) { return process.memoryUsage().heapUsed; } return 0; } static sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } static calculateMemoryEfficiency(memoryUsages) { const maxUsage = Math.max(...memoryUsages.map(Math.abs)); const avgUsage = memoryUsages.reduce((a, b) => a + Math.abs(b), 0) / memoryUsages.length; if (maxUsage === 0) return 1; return 1 - avgUsage / maxUsage; } static calculateScalabilityScore(times) { if (times.length < 2) return 1; // Calculate coefficient of variation (lower is better for scalability) const mean = times.reduce((a, b) => a + b, 0) / times.length; const variance = times.reduce((sum, time) => sum + Math.pow(time - mean, 2), 0) / times.length; const stdDev = Math.sqrt(variance); const coefficientOfVariation = stdDev / mean; // Convert to 0-1 score (1 is best) return Math.max(0, 1 - coefficientOfVariation); } static generateRecommendations(averageDuration, averageMemoryUsage, operationBreakdown, totalOperations) { const recommendations = []; if (averageDuration > 100) { recommendations.push("Consider optimizing operations - average duration is high"); } if (averageMemoryUsage > 1000000) { recommendations.push("High memory usage detected - consider memory optimization"); } const cryptoOps = operationBreakdown["hash"] || 0; if (cryptoOps / totalOperations > 0.5) { recommendations.push("High cryptographic operation usage - consider caching results"); } return recommendations; } static generateBenchmarkRecommendations(averageTime, memoryEfficiency, scalabilityScore) { const recommendations = []; if (averageTime > 50) { recommendations.push("Operation time is high - consider optimization"); } if (memoryEfficiency < 0.7) { recommendations.push("Memory efficiency is low - review memory usage patterns"); } if (scalabilityScore < 0.8) { recommendations.push("Performance variability is high - investigate consistency issues"); } return recommendations; } static getEmptyStats() { return { totalOperations: 0, averageDuration: 0, minDuration: 0, maxDuration: 0, totalMemoryUsed: 0, averageMemoryUsage: 0, operationBreakdown: {}, throughputStats: { average: 0, peak: 0, current: 0, }, recommendations: [], }; } } PerformanceMonitor.metrics = []; PerformanceMonitor.isMonitoring = false; PerformanceMonitor.maxMetricsHistory = 1000; exports.PerformanceMonitor = PerformanceMonitor; //# sourceMappingURL=performance-monitor.js.map