UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and

211 lines (210 loc) • 6.71 kB
/** * Performance measurement and memory management utilities * Part of Sub-phase 3.3.1-3.3.2 optimization efforts */ import { logger } from "./logger.js"; /** * Performance measurement utility for tracking operations */ export class PerformanceTracker { metrics = new Map(); /** * Start tracking performance for an operation */ start(operationName) { this.metrics.set(operationName, { startTime: Date.now(), memoryStart: process.memoryUsage(), }); } /** * End tracking and calculate metrics */ end(operationName) { const metric = this.metrics.get(operationName); if (!metric) { return null; } const endTime = Date.now(); const memoryEnd = process.memoryUsage(); const completedMetric = { ...metric, endTime, duration: endTime - metric.startTime, memoryEnd, memoryDelta: { rss: memoryEnd.rss - metric.memoryStart.rss, heapTotal: memoryEnd.heapTotal - metric.memoryStart.heapTotal, heapUsed: memoryEnd.heapUsed - metric.memoryStart.heapUsed, external: memoryEnd.external - metric.memoryStart.external, }, }; this.metrics.set(operationName, completedMetric); return completedMetric; } /** * Get metrics for an operation */ getMetrics(operationName) { return this.metrics.get(operationName) || null; } /** * Clear all metrics */ clear() { this.metrics.clear(); } /** * Format metrics for display */ formatMetrics(operationName) { const metric = this.metrics.get(operationName); if (!metric || !metric.duration) { return `${operationName}: No metrics available`; } const memoryMB = (bytes) => (bytes / 1024 / 1024).toFixed(1); return [ `${operationName}:`, ` Duration: ${metric.duration}ms`, ` Memory Delta: +${memoryMB(metric.memoryDelta.heapUsed)}MB heap`, ` RSS Delta: +${memoryMB(metric.memoryDelta.rss)}MB`, ].join("\n"); } } /** * Global performance tracker instance */ export const globalTracker = new PerformanceTracker(); /** * Memory management utilities */ export class MemoryManager { /** * Force garbage collection if available */ static forceGC() { if (typeof global !== "undefined" && global.gc) { global.gc(); return true; } return false; } /** * Get current memory usage in MB */ static getMemoryUsageMB() { const usage = process.memoryUsage(); return { rss: Math.round(usage.rss / 1024 / 1024), heapTotal: Math.round(usage.heapTotal / 1024 / 1024), heapUsed: Math.round(usage.heapUsed / 1024 / 1024), external: Math.round(usage.external / 1024 / 1024), }; } /** * Monitor memory usage and warn if it exceeds threshold */ static monitorMemory(threshold = 100) { const usage = this.getMemoryUsageMB(); if (usage.heapUsed > threshold) { logger.warn(`āš ļø High memory usage: ${usage.heapUsed}MB heap (threshold: ${threshold}MB)`); return true; } return false; } /** * Clean up and optimize memory usage. * Attempts to force garbage collection if available. * * @returns {object|null} Memory usage statistics if cleanup was performed, or null if not possible. * - If manual garbage collection is not available (i.e., Node.js not run with --expose-gc), * no cleanup is performed and null is returned. * - Clearing the require cache is not attempted due to potential side effects. */ static cleanup() { const before = this.getMemoryUsageMB(); const gcForced = this.forceGC(); if (!gcForced) { // Manual garbage collection not available. // No cleanup performed. Clearing require cache is dangerous and not attempted. // Memory cleanup relies on Node.js natural garbage collection. return null; } const after = this.getMemoryUsageMB(); return { beforeMB: before.heapUsed, afterMB: after.heapUsed, freedMB: before.heapUsed - after.heapUsed, }; } } /** * Decorator for tracking performance of async functions */ export function trackPerformance(operationName) { return function (target, propertyName, descriptor) { const method = descriptor.value; descriptor.value = async function (...args) { globalTracker.start(operationName); try { const result = await method.apply(this, args); globalTracker.end(operationName); return result; } catch (error) { globalTracker.end(operationName); throw error; } }; return descriptor; }; } /** * Performance monitoring for CLI operations */ export class CLIPerformanceMonitor { static instance; enabled = false; static getInstance() { if (!CLIPerformanceMonitor.instance) { CLIPerformanceMonitor.instance = new CLIPerformanceMonitor(); } return CLIPerformanceMonitor.instance; } enable() { this.enabled = true; } disable() { this.enabled = false; } /** * Monitor a CLI operation */ async monitorOperation(operationName, operation) { if (!this.enabled) { return operation(); } globalTracker.start(operationName); const startMemory = MemoryManager.getMemoryUsageMB(); try { const result = await operation(); const metrics = globalTracker.end(operationName); const endMemory = MemoryManager.getMemoryUsageMB(); if (metrics) { logger.debug(`\nšŸ” Performance: ${operationName}`); logger.debug(` Duration: ${metrics.duration}ms`); logger.debug(` Memory: ${startMemory.heapUsed}MB → ${endMemory.heapUsed}MB`); logger.debug(` Delta: +${endMemory.heapUsed - startMemory.heapUsed}MB`); } return result; } catch (error) { globalTracker.end(operationName); throw error; } } } /** * Export singleton monitor for easy access */ export const cliMonitor = CLIPerformanceMonitor.getInstance();