UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

369 lines (368 loc) 13.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resourceBenchmarks = exports.ResourceBenchmarks = void 0; /** * Resource usage testing and benchmarking */ const perf_hooks_1 = require("perf_hooks"); const child_process_1 = require("child_process"); class ResourceBenchmarks { constructor() { this.benchmarkHistory = []; this.monitoring = false; this.memoryPeak = 0; } static getInstance() { if (!ResourceBenchmarks.instance) { ResourceBenchmarks.instance = new ResourceBenchmarks(); } return ResourceBenchmarks.instance; } /** * Run a single benchmark */ async benchmark(name, operation, iterations = 1, metadata) { const startTime = perf_hooks_1.performance.now(); const memoryBefore = process.memoryUsage(); const cpuBefore = process.cpuUsage(); this.startMemoryMonitoring(); let success = true; let error; try { for (let i = 0; i < iterations; i++) { await operation(); } } catch (err) { success = false; error = err instanceof Error ? err.message : String(err); } const endTime = perf_hooks_1.performance.now(); const memoryAfter = process.memoryUsage(); const cpuAfter = process.cpuUsage(cpuBefore); this.stopMemoryMonitoring(); const result = { name, duration: endTime - startTime, memoryBefore, memoryAfter, memoryPeak: this.memoryPeak, memoryDelta: memoryAfter.heapUsed - memoryBefore.heapUsed, cpuBefore, cpuAfter, cpuUsage: (cpuAfter.user + cpuAfter.system) / 1000, // microseconds to milliseconds startTime, endTime, iterations, success, error, metadata }; this.benchmarkHistory.push(result); return result; } /** * Run a benchmark suite */ async benchmarkSuite(suiteName, benchmarks) { const results = []; for (const benchmark of benchmarks) { const result = await this.benchmark(benchmark.name, benchmark.operation, benchmark.iterations || 1, benchmark.metadata); results.push(result); } const summary = this.calculateSuiteSummary(results); return { name: suiteName, results, summary }; } /** * Run CLI startup benchmark */ async benchmarkStartup(cliPath, args = ['--version'], iterations = 10) { return this.benchmark('CLI Startup', async () => { return new Promise((resolve, reject) => { const startTime = perf_hooks_1.performance.now(); const child = (0, child_process_1.spawn)('node', [cliPath, ...args], { stdio: 'ignore' }); child.on('close', (code) => { const endTime = perf_hooks_1.performance.now(); if (code === 0) { resolve(); } else { reject(new Error(`CLI exited with code ${code}`)); } }); child.on('error', reject); // Timeout after 10 seconds setTimeout(() => { child.kill(); reject(new Error('CLI startup timeout')); }, 10000); }); }, iterations, { cliPath, args }); } /** * Run memory stress test */ async memoryStressTest(allocations = 1000, allocationSize = 1024 * 1024 // 1MB ) { return this.benchmark('Memory Stress Test', async () => { const allocatedBuffers = []; // Allocate memory for (let i = 0; i < allocations; i++) { const buffer = Buffer.alloc(allocationSize); buffer.fill(i % 256); // Fill with data to prevent optimization allocatedBuffers.push(buffer); // Yield control occasionally if (i % 100 === 0) { await new Promise(resolve => setImmediate(resolve)); } } // Force GC if available if (global.gc) { global.gc(); } // Keep references to prevent early GC return allocatedBuffers.length; }, 1, { allocations, allocationSize }); } /** * Run CPU stress test */ async cpuStressTest(duration = 1000, // milliseconds complexity = 1000000) { return this.benchmark('CPU Stress Test', async () => { const startTime = Date.now(); let operations = 0; while (Date.now() - startTime < duration) { // Perform CPU-intensive calculation for (let i = 0; i < complexity; i++) { Math.sqrt(Math.random() * Math.PI); operations++; } // Yield control await new Promise(resolve => setImmediate(resolve)); } return operations; }, 1, { duration, complexity }); } /** * Run concurrent operations test */ async concurrencyTest(concurrency = 10, operationDuration = 100 // milliseconds ) { return this.benchmark('Concurrency Test', async () => { const operations = []; for (let i = 0; i < concurrency; i++) { operations.push(new Promise(resolve => { setTimeout(resolve, operationDuration + Math.random() * operationDuration); })); } await Promise.all(operations); }, 1, { concurrency, operationDuration }); } /** * Run load test */ async loadTest(config) { const results = []; const startTime = Date.now(); const memoryInitial = process.memoryUsage().heapUsed / 1024 / 1024; let memoryPeak = memoryInitial; // Start memory monitoring const memoryMonitor = setInterval(() => { const current = process.memoryUsage().heapUsed / 1024 / 1024; memoryPeak = Math.max(memoryPeak, current); }, 100); try { const workers = []; const rampUpDelay = (config.rampUp * 1000) / config.concurrent; for (let i = 0; i < config.concurrent; i++) { const worker = this.createLoadTestWorker(config, results, i * rampUpDelay); workers.push(worker); } // Wait for test duration await new Promise(resolve => setTimeout(resolve, config.duration * 1000)); // Let workers finish current operations await Promise.allSettled(workers); } finally { clearInterval(memoryMonitor); } const endTime = Date.now(); const actualDuration = (endTime - startTime) / 1000; const memoryFinal = process.memoryUsage().heapUsed / 1024 / 1024; // Calculate statistics const successful = results.filter(r => r.success); const failed = results.filter(r => !r.success); const durations = successful.map(r => r.duration).sort((a, b) => a - b); return { config, results: { totalOperations: results.length, successfulOperations: successful.length, failedOperations: failed.length, operationsPerSecond: results.length / actualDuration, averageResponseTime: durations.length > 0 ? durations.reduce((sum, d) => sum + d, 0) / durations.length : 0, percentiles: { p50: durations[Math.floor(durations.length * 0.5)] || 0, p95: durations[Math.floor(durations.length * 0.95)] || 0, p99: durations[Math.floor(durations.length * 0.99)] || 0 }, memoryUsage: { initial: memoryInitial, peak: memoryPeak, final: memoryFinal }, errors: failed.map(f => f.error || 'Unknown error') } }; } /** * Get benchmark history */ getHistory() { return [...this.benchmarkHistory]; } /** * Get performance baseline */ getBaseline() { const startupBenchmarks = this.benchmarkHistory.filter(b => b.name === 'CLI Startup'); const memoryBenchmarks = this.benchmarkHistory.filter(b => b.name === 'Memory Stress Test'); const cpuBenchmarks = this.benchmarkHistory.filter(b => b.name === 'CPU Stress Test'); return { startupTime: startupBenchmarks.length > 0 ? startupBenchmarks.reduce((sum, b) => sum + b.duration, 0) / startupBenchmarks.length : 0, memoryUsage: memoryBenchmarks.length > 0 ? memoryBenchmarks.reduce((sum, b) => sum + b.memoryDelta, 0) / memoryBenchmarks.length : 0, cpuEfficiency: cpuBenchmarks.length > 0 ? cpuBenchmarks.reduce((sum, b) => sum + b.cpuUsage, 0) / cpuBenchmarks.length : 0 }; } /** * Clear benchmark history */ clearHistory() { this.benchmarkHistory = []; } /** * Export benchmark results */ exportResults(format = 'json') { if (format === 'csv') { const headers = [ 'name', 'duration', 'memoryDelta', 'cpuUsage', 'iterations', 'success', 'startTime', 'endTime' ]; const rows = this.benchmarkHistory.map(result => [ result.name, result.duration, result.memoryDelta, result.cpuUsage, result.iterations, result.success, result.startTime, result.endTime ]); return [headers.join(','), ...rows.map(row => row.join(','))].join('\n'); } else { return JSON.stringify(this.benchmarkHistory, null, 2); } } /** * Start memory monitoring */ startMemoryMonitoring() { if (this.monitoring) return; this.monitoring = true; this.memoryPeak = process.memoryUsage().heapUsed; const monitor = () => { if (!this.monitoring) return; const current = process.memoryUsage().heapUsed; this.memoryPeak = Math.max(this.memoryPeak, current); setImmediate(monitor); }; monitor(); } /** * Stop memory monitoring */ stopMemoryMonitoring() { this.monitoring = false; } /** * Calculate suite summary */ calculateSuiteSummary(results) { const totalDuration = results.reduce((sum, r) => sum + r.duration, 0); const successful = results.filter(r => r.success); return { totalDuration, averageDuration: results.length > 0 ? totalDuration / results.length : 0, memoryEfficiency: successful.length > 0 ? successful.reduce((sum, r) => sum + (r.memoryDelta / r.duration), 0) / successful.length : 0, cpuEfficiency: successful.length > 0 ? successful.reduce((sum, r) => sum + (r.cpuUsage / r.duration), 0) / successful.length : 0, successRate: results.length > 0 ? (successful.length / results.length) * 100 : 0 }; } /** * Create load test worker */ async createLoadTestWorker(config, results, delay) { // Initial delay for ramp-up if (delay > 0) { await new Promise(resolve => setTimeout(resolve, delay)); } const endTime = Date.now() + (config.duration * 1000); const totalWeight = config.operations.reduce((sum, op) => sum + op.weight, 0); while (Date.now() < endTime) { // Select operation based on weight const random = Math.random() * totalWeight; let currentWeight = 0; let selectedOperation = config.operations[0]; for (const operation of config.operations) { currentWeight += operation.weight; if (random <= currentWeight) { selectedOperation = operation; break; } } // Execute operation const startTime = perf_hooks_1.performance.now(); try { await selectedOperation.operation(); const duration = perf_hooks_1.performance.now() - startTime; results.push({ success: true, duration }); } catch (error) { const duration = perf_hooks_1.performance.now() - startTime; results.push({ success: false, duration, error: error instanceof Error ? error.message : String(error) }); } // Small delay between operations await new Promise(resolve => setImmediate(resolve)); } } } exports.ResourceBenchmarks = ResourceBenchmarks; // Export singleton instance exports.resourceBenchmarks = ResourceBenchmarks.getInstance();