@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
JavaScript
;
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();