UNPKG

ccusage-byobu

Version:

Real-time Claude Code API usage monitoring for byobu/tmux status bars with colored indicators, persistent caching, and automated integration

162 lines (141 loc) 3.76 kB
/** * Performance measurement utilities for ccusage-byobu * Used to benchmark startup time and optimization effectiveness */ /** * Simple performance timer */ class PerformanceTimer { constructor() { this.startTime = null; this.endTime = null; } start() { this.startTime = process.hrtime.bigint(); return this; } stop() { this.endTime = process.hrtime.bigint(); return this; } getDuration() { if (!this.startTime || !this.endTime) { throw new Error('Timer not properly started/stopped'); } const durationNs = this.endTime - this.startTime; const durationMs = Number(durationNs) / 1000000; // Convert to milliseconds return { nanoseconds: Number(durationNs), milliseconds: durationMs, seconds: durationMs / 1000, }; } format() { const duration = this.getDuration(); if (duration.milliseconds < 1) { return `${duration.nanoseconds}ns`; } else if (duration.milliseconds < 1000) { return `${duration.milliseconds.toFixed(2)}ms`; } else { return `${duration.seconds.toFixed(3)}s`; } } } /** * Create a new performance timer * @returns {PerformanceTimer} New timer instance */ export function createTimer() { return new PerformanceTimer(); } /** * Measure memory usage * @returns {Object} Memory usage information */ export function getMemoryUsage() { const usage = process.memoryUsage(); return { rss: { bytes: usage.rss, mb: (usage.rss / 1024 / 1024).toFixed(2), }, heapTotal: { bytes: usage.heapTotal, mb: (usage.heapTotal / 1024 / 1024).toFixed(2), }, heapUsed: { bytes: usage.heapUsed, mb: (usage.heapUsed / 1024 / 1024).toFixed(2), }, external: { bytes: usage.external, mb: (usage.external / 1024 / 1024).toFixed(2), }, }; } /** * Benchmark a function execution * @param {Function} fn - Function to benchmark * @param {string} name - Name for the benchmark * @returns {Promise<Object>} Benchmark results */ export async function benchmark(fn, name = 'operation') { const timer = createTimer(); const initialMemory = getMemoryUsage(); timer.start(); let result; let error = null; try { result = fn(); // Check if result is a Promise by verifying it has a then method if (result && typeof result.then === 'function') { result = await result; } } catch (err) { error = err; } timer.stop(); const finalMemory = getMemoryUsage(); const memoryDelta = { rss: finalMemory.rss.bytes - initialMemory.rss.bytes, heapUsed: finalMemory.heapUsed.bytes - initialMemory.heapUsed.bytes, }; return { name, duration: timer.getDuration(), durationFormatted: timer.format(), memory: { initial: initialMemory, final: finalMemory, delta: { rss: { bytes: memoryDelta.rss, mb: (memoryDelta.rss / 1024 / 1024).toFixed(2), }, heapUsed: { bytes: memoryDelta.heapUsed, mb: (memoryDelta.heapUsed / 1024 / 1024).toFixed(2), }, }, }, result, error, success: error === null, }; } /** * Log benchmark results in a readable format * @param {Object} benchmark - Benchmark results from benchmark() */ export function logBenchmark(benchmark) { const status = benchmark.success ? '✅' : '❌'; console.log(`${status} ${benchmark.name}: ${benchmark.durationFormatted}`); if (process.env.CCUSAGE_BYOBU_DEBUG) { console.log( ` Memory delta: RSS ${benchmark.memory.delta.rss.mb}MB, Heap ${benchmark.memory.delta.heapUsed.mb}MB` ); if (benchmark.error) { console.log(` Error: ${benchmark.error.message}`); } } }