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