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

191 lines (190 loc) 6.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.profiler = exports.PerformanceProfiler = void 0; /** * Performance profiler for CLI startup and command execution */ const perf_hooks_1 = require("perf_hooks"); const fs_1 = require("fs"); const path_1 = require("path"); const os_1 = require("os"); class PerformanceProfiler { constructor() { this.marks = new Map(); this.startTime = 0; this.enabled = false; const cacheDir = (0, path_1.join)((0, os_1.homedir)(), '.re-shell', 'performance'); if (!(0, fs_1.existsSync)(cacheDir)) { (0, fs_1.mkdirSync)(cacheDir, { recursive: true }); } this.reportPath = (0, path_1.join)(cacheDir, 'performance.json'); // Enable profiling based on environment variable this.enabled = process.env.RESHELL_PROFILE === 'true' || process.env.DEBUG === 'true'; } static getInstance() { if (!PerformanceProfiler.instance) { PerformanceProfiler.instance = new PerformanceProfiler(); } return PerformanceProfiler.instance; } /** * Start profiling */ start(command = 'unknown') { if (!this.enabled) return; this.startTime = perf_hooks_1.performance.now(); this.marks.clear(); this.mark('startup', { command, argv: process.argv.slice(2).join(' ') }); } /** * Mark a performance checkpoint */ mark(name, metadata) { if (!this.enabled) return; const timestamp = perf_hooks_1.performance.now(); const memory = process.memoryUsage(); this.marks.set(name, { name, timestamp, memory, ...(metadata && { metadata }) }); } /** * Measure duration between two marks */ measure(name, startMark, endMark) { if (!this.enabled) return; const start = this.marks.get(startMark); const end = endMark ? this.marks.get(endMark) : { timestamp: perf_hooks_1.performance.now() }; if (start && end) { const duration = end.timestamp - start.timestamp; this.marks.set(name, { name, timestamp: end.timestamp, duration }); } } /** * End profiling and generate report */ end() { if (!this.enabled) return null; const endTime = perf_hooks_1.performance.now(); const totalDuration = endTime - this.startTime; const report = { startTime: this.startTime, endTime, totalDuration, marks: Array.from(this.marks.values()), command: process.argv.slice(2).join(' ') || 'none', version: require('../../package.json').version, platform: process.platform, nodeVersion: process.version }; // Save report this.saveReport(report); if (process.env.DEBUG === 'true') { this.printReport(report); } return report; } /** * Save performance report */ saveReport(report) { try { let reports = []; if ((0, fs_1.existsSync)(this.reportPath)) { const existing = (0, fs_1.readFileSync)(this.reportPath, 'utf-8'); reports = JSON.parse(existing); } // Keep only last 100 reports reports.push(report); if (reports.length > 100) { reports = reports.slice(-100); } (0, fs_1.writeFileSync)(this.reportPath, JSON.stringify(reports, null, 2)); } catch (error) { // Ignore save errors } } /** * Print performance report to console */ printReport(report) { console.log('\n=== Performance Report ==='); console.log(`Total Duration: ${report.totalDuration.toFixed(2)}ms`); console.log(`Command: ${report.command}`); console.log(`Platform: ${report.platform} (Node ${report.nodeVersion})`); console.log('\nTimings:'); const sortedMarks = report.marks.sort((a, b) => a.timestamp - b.timestamp); let lastTime = 0; for (const mark of sortedMarks) { const delta = mark.timestamp - lastTime; const fromStart = mark.timestamp - report.startTime; console.log(` ${mark.name.padEnd(30)} +${delta.toFixed(2).padStart(8)}ms (${fromStart.toFixed(2).padStart(8)}ms from start)`); if (mark.duration) { console.log(` └─ Duration: ${mark.duration.toFixed(2)}ms`); } if (mark.memory) { const heapMB = (mark.memory.heapUsed / 1024 / 1024).toFixed(2); console.log(` └─ Memory: ${heapMB}MB`); } lastTime = mark.timestamp; } console.log('========================\n'); } /** * Get average startup time from recent reports */ getAverageStartupTime() { if (!(0, fs_1.existsSync)(this.reportPath)) { return null; } try { const reports = JSON.parse((0, fs_1.readFileSync)(this.reportPath, 'utf-8')); if (reports.length === 0) return null; const recentReports = reports.slice(-10); const avgTime = recentReports.reduce((sum, r) => sum + r.totalDuration, 0) / recentReports.length; return avgTime; } catch { return null; } } /** * Analyze performance bottlenecks */ analyzeBottlenecks() { const marks = Array.from(this.marks.values()).sort((a, b) => a.timestamp - b.timestamp); const bottlenecks = []; for (let i = 0; i < marks.length - 1; i++) { const current = marks[i]; const next = marks[i + 1]; const duration = next.timestamp - current.timestamp; const percentage = (duration / (perf_hooks_1.performance.now() - this.startTime)) * 100; if (duration > 10) { // Only report phases taking more than 10ms bottlenecks.push({ phase: `${current.name}${next.name}`, duration, percentage }); } } return bottlenecks.sort((a, b) => b.duration - a.duration); } } exports.PerformanceProfiler = PerformanceProfiler; // Export singleton instance exports.profiler = PerformanceProfiler.getInstance();