Skip to main content
Glama

Prompt Auto-Optimizer MCP

by sloth-wq
gc-optimizer.ts35.4 kB
/** * Garbage Collection Optimizer for GEPA * * Provides comprehensive GC optimization strategies, object pooling, and memory management * for high-performance GEPA workloads with adaptive tuning and real-time monitoring. */ import { EventEmitter } from 'events'; import { performance } from 'perf_hooks'; import { PerformanceTracker, PerformanceMetricData } from '../services/performance-tracker'; import { MemoryLeakDetector, MemoryLeakIntegration } from './memory-leak-detector'; /** * GC optimization strategies based on workload characteristics */ export interface GCOptimizationStrategy { name: string; description: string; targetWorkloads: string[]; gcTuning: { /** Maximum heap size before forcing GC (MB) */ maxHeapSize: number; /** Trigger GC when heap usage exceeds this percentage */ heapUsageThreshold: number; /** Time between forced GC cycles (ms) */ forcedGCInterval: number; /** Use incremental GC for large heaps */ incrementalGC: boolean; /** Maximum pause time for incremental GC (ms) */ maxPauseTime: number; }; objectLifecycle: { /** Short-lived object threshold (ms) */ shortLivedThreshold: number; /** Long-lived object threshold (ms) */ longLivedThreshold: number; /** Enable generational GC optimization */ generationalOptimization: boolean; }; } /** * Object pool configuration for different object types */ export interface ObjectPoolConfig { /** Pool name/identifier */ name: string; /** Maximum pool size */ maxSize: number; /** Minimum pool size to maintain */ minSize: number; /** Object factory function */ factory: () => any; /** Object reset function */ reset?: (obj: any) => void; /** Object validation function */ validate?: (obj: any) => boolean; /** Pool eviction strategy */ evictionStrategy: 'lru' | 'fifo' | 'random' | 'ttl'; /** TTL for objects in pool (ms) */ ttl?: number; /** Enable pool size auto-tuning */ autoTune: boolean; } /** * Memory management strategy configuration */ export interface MemoryManagementConfig { /** Enable lazy cleanup */ lazyCleanup: boolean; /** Cleanup trigger threshold (memory pressure level 0-1) */ cleanupThreshold: number; /** Buffer reuse patterns */ bufferReuse: { enabled: boolean; poolSizes: number[]; maxBuffers: number; }; /** Resource recycling configuration */ resourceRecycling: { enabled: boolean; recycleInterval: number; maxRecycleAge: number; }; } /** * GC metrics collected during optimization */ export interface GCMetrics { timestamp: number; type: 'minor' | 'major' | 'incremental' | 'forced'; duration: number; heapBefore: number; heapAfter: number; heapReclaimed: number; pauseTime: number; efficiency: number; triggerReason: string; } /** * Object pool statistics */ export interface PoolStatistics { name: string; currentSize: number; maxSize: number; hits: number; misses: number; creates: number; destroys: number; hitRate: number; utilizationRate: number; averageLifetime: number; } /** * Memory pressure levels for adaptive responses */ export type MemoryPressureLevel = 'low' | 'medium' | 'high' | 'critical'; /** * Memory pressure response handler */ export interface MemoryPressureHandler { level: MemoryPressureLevel; priority: number; action: (metrics: GCMetrics) => Promise<void>; description: string; } /** * Main Garbage Collection Optimizer */ export class GarbageCollectionOptimizer extends EventEmitter { private performanceTracker: PerformanceTracker; private memoryLeakDetector: MemoryLeakDetector; private isEnabled = true; private monitoringInterval?: ReturnType<typeof setInterval>; private forcedGCInterval?: ReturnType<typeof setInterval>; // GC optimization state private currentStrategy: GCOptimizationStrategy; private gcMetricsHistory: GCMetrics[] = []; private objectPools = new Map<string, ObjectPool<any>>(); private memoryPressureHandlers: MemoryPressureHandler[] = []; private bufferPools = new Map<number, Buffer[]>(); // Adaptive tuning state private adaptiveTuning = { enabled: true, learningRate: 0.1, performanceBaseline: 0, lastTuningTime: 0, tuningCooldown: 60000, // 1 minute }; // Memory management configuration private memoryConfig: MemoryManagementConfig = { lazyCleanup: true, cleanupThreshold: 0.8, bufferReuse: { enabled: true, poolSizes: [1024, 4096, 16384, 65536, 262144], // Common buffer sizes maxBuffers: 100, }, resourceRecycling: { enabled: true, recycleInterval: 30000, // 30 seconds maxRecycleAge: 300000, // 5 minutes }, }; constructor( performanceTracker: PerformanceTracker, memoryLeakDetector?: MemoryLeakDetector ) { super(); this.performanceTracker = performanceTracker; this.memoryLeakDetector = memoryLeakDetector || MemoryLeakIntegration.getDetector()!; // Initialize with balanced strategy this.currentStrategy = this.createBalancedStrategy(); this.initializeObjectPools(); this.initializeMemoryPressureHandlers(); this.initializeBufferPools(); this.startMonitoring(); this.setupGCHooks(); } /** * Set GC optimization strategy based on workload type */ setOptimizationStrategy(workloadType: string): void { let strategy: GCOptimizationStrategy; switch (workloadType) { case 'high-throughput': strategy = this.createHighThroughputStrategy(); break; case 'low-latency': strategy = this.createLowLatencyStrategy(); break; case 'memory-intensive': strategy = this.createMemoryIntensiveStrategy(); break; case 'batch-processing': strategy = this.createBatchProcessingStrategy(); break; default: strategy = this.createBalancedStrategy(); } this.currentStrategy = strategy; this.applyStrategy(strategy); this.emit('strategyChanged', { workloadType, strategy }); } /** * Create and register an object pool */ createObjectPool<T>(config: ObjectPoolConfig): ObjectPool<T> { const pool = new ObjectPool<T>(config); this.objectPools.set(config.name, pool); // Hook pool events for monitoring pool.on('hit', (stats) => this.emit('poolHit', { pool: config.name, stats })); pool.on('miss', (stats) => this.emit('poolMiss', { pool: config.name, stats })); pool.on('eviction', (stats) => this.emit('poolEviction', { pool: config.name, stats })); this.emit('poolCreated', { name: config.name, config }); return pool; } /** * Get an object pool by name */ getObjectPool<T>(name: string): ObjectPool<T> | undefined { return this.objectPools.get(name) as ObjectPool<T>; } /** * Force garbage collection with optimization */ async forceGarbageCollection(reason: string = 'manual'): Promise<GCMetrics> { const startTime = performance.now(); const beforeMemory = process.memoryUsage(); // Pre-GC cleanup await this.performLazyCleanup(); // Force GC if available if (global.gc) { global.gc(); } const endTime = performance.now(); const afterMemory = process.memoryUsage(); const metrics: GCMetrics = { timestamp: Date.now(), type: 'forced', duration: endTime - startTime, heapBefore: beforeMemory.heapUsed, heapAfter: afterMemory.heapUsed, heapReclaimed: beforeMemory.heapUsed - afterMemory.heapUsed, pauseTime: endTime - startTime, efficiency: (beforeMemory.heapUsed - afterMemory.heapUsed) / beforeMemory.heapUsed, triggerReason: reason, }; this.recordGCMetrics(metrics); return metrics; } /** * Get buffer from reuse pool or create new one */ getBuffer(size: number): Buffer { if (!this.memoryConfig.bufferReuse.enabled) { return Buffer.alloc(size); } // Find closest pool size const poolSize = this.memoryConfig.bufferReuse.poolSizes .find(s => s >= size) || size; const pool = this.bufferPools.get(poolSize); if (pool && pool.length > 0) { const buffer = pool.pop()!; // Reset buffer content buffer.fill(0); this.performanceTracker.recordMetric({ id: `buffer-reuse-${Date.now()}`, name: 'buffer-reuse', category: 'memory-optimization', timestamp: Date.now(), data: { size: poolSize, poolSize: pool.length } as PerformanceMetricData, }); return buffer.subarray(0, size); } return Buffer.alloc(size); } /** * Return buffer to reuse pool */ returnBuffer(buffer: Buffer): void { if (!this.memoryConfig.bufferReuse.enabled) { return; } const size = buffer.length; const poolSize = this.memoryConfig.bufferReuse.poolSizes .find(s => s >= size); if (poolSize) { const pool = this.bufferPools.get(poolSize); if (pool && pool.length < this.memoryConfig.bufferReuse.maxBuffers) { // Ensure buffer is the right size const poolBuffer = poolSize === size ? buffer : Buffer.alloc(poolSize); if (poolSize !== size) { buffer.copy(poolBuffer); } pool.push(poolBuffer); } } } /** * Analyze memory allocation patterns */ analyzeAllocationPatterns(): { hotspots: Array<{ component: string; allocationsPerSecond: number; averageSize: number }>; patterns: Array<{ pattern: string; frequency: number; impact: number }>; recommendations: string[]; } { const gcHistory = this.gcMetricsHistory.slice(-50); // Last 50 GC cycles const recommendations: string[] = []; // Analyze GC frequency and efficiency const avgGCInterval = this.calculateAverageGCInterval(gcHistory); const avgEfficiency = gcHistory.reduce((sum, gc) => sum + gc.efficiency, 0) / gcHistory.length; if (avgGCInterval < 5000) { // Less than 5 seconds recommendations.push('High GC frequency detected - consider object pooling'); } if (avgEfficiency < 0.2) { // Less than 20% memory reclaimed recommendations.push('Low GC efficiency - check for memory leaks'); } // Analyze object pool performance const poolStats = Array.from(this.objectPools.values()).map(pool => pool.getStatistics()); const lowHitRatePools = poolStats.filter(stats => stats.hitRate < 0.5); if (lowHitRatePools.length > 0) { recommendations.push(`Object pools with low hit rates: ${lowHitRatePools.map(p => p.name).join(', ')}`); } return { hotspots: [], // Would be populated with real allocation tracking patterns: [], // Would be populated with pattern analysis recommendations, }; } /** * Get comprehensive memory optimization statistics */ getOptimizationStatistics(): { gcMetrics: { totalCollections: number; averageDuration: number; averageEfficiency: number; memoryReclaimed: number; }; objectPools: PoolStatistics[]; memoryPressure: { currentLevel: MemoryPressureLevel; responseTime: number; handlersExecuted: number; }; bufferReuse: { totalReuses: number; poolUtilization: Array<{ size: number; usage: number }>; memoryEfficiency: number; }; adaptiveTuning: { enabled: boolean; lastTuning: number; performanceGain: number; strategyEffectiveness: number; }; } { const gcHistory = this.gcMetricsHistory; const poolStats = Array.from(this.objectPools.values()).map(pool => pool.getStatistics()); return { gcMetrics: { totalCollections: gcHistory.length, averageDuration: gcHistory.reduce((sum, gc) => sum + gc.duration, 0) / gcHistory.length || 0, averageEfficiency: gcHistory.reduce((sum, gc) => sum + gc.efficiency, 0) / gcHistory.length || 0, memoryReclaimed: gcHistory.reduce((sum, gc) => sum + gc.heapReclaimed, 0), }, objectPools: poolStats, memoryPressure: { currentLevel: this.getCurrentMemoryPressureLevel(), responseTime: 0, // Would track actual response times handlersExecuted: 0, // Would track handler executions }, bufferReuse: { totalReuses: 0, // Would track from metrics poolUtilization: Array.from(this.bufferPools.entries()).map(([size, buffers]) => ({ size, usage: buffers.length / this.memoryConfig.bufferReuse.maxBuffers, })), memoryEfficiency: 0, // Would calculate from reuse metrics }, adaptiveTuning: { enabled: this.adaptiveTuning.enabled, lastTuning: this.adaptiveTuning.lastTuningTime, performanceGain: 0, // Would calculate from performance metrics strategyEffectiveness: 0, // Would calculate from strategy performance }, }; } /** * Shutdown GC optimizer */ shutdown(): void { this.isEnabled = false; if (this.monitoringInterval) { clearInterval(this.monitoringInterval); } if (this.forcedGCInterval) { clearInterval(this.forcedGCInterval); } // Shutdown object pools for (const pool of Array.from(this.objectPools.values())) { pool.shutdown(); } this.emit('shutdown'); } // Private Methods private initializeObjectPools(): void { // Create pools for common GEPA objects // Candidate object pool this.createObjectPool({ name: 'candidates', maxSize: 1000, minSize: 100, factory: () => ({ id: '', fitness: 0, objectives: [], metadata: {}, timestamp: 0, }), reset: (obj) => { obj.id = ''; obj.fitness = 0; obj.objectives.length = 0; obj.metadata = {}; obj.timestamp = 0; }, evictionStrategy: 'lru', autoTune: true, }); // Trajectory data pool this.createObjectPool({ name: 'trajectory-data', maxSize: 500, minSize: 50, factory: () => ({ steps: [], metadata: {}, startTime: 0, endTime: 0, }), reset: (obj) => { obj.steps.length = 0; obj.metadata = {}; obj.startTime = 0; obj.endTime = 0; }, evictionStrategy: 'ttl', ttl: 300000, // 5 minutes autoTune: true, }); // Analysis result pool this.createObjectPool({ name: 'analysis-results', maxSize: 200, minSize: 20, factory: () => ({ type: '', data: {}, score: 0, timestamp: 0, cached: false, }), reset: (obj) => { obj.type = ''; obj.data = {}; obj.score = 0; obj.timestamp = 0; obj.cached = false; }, evictionStrategy: 'fifo', autoTune: true, }); } private initializeMemoryPressureHandlers(): void { // Critical level - immediate action this.memoryPressureHandlers.push({ level: 'critical', priority: 1, action: async (_metrics) => { await this.forceGarbageCollection('critical-pressure'); await this.performAggressiveCleanup(); }, description: 'Force GC and aggressive cleanup', }); // High level - proactive cleanup this.memoryPressureHandlers.push({ level: 'high', priority: 2, action: async (_metrics) => { await this.performLazyCleanup(); await this.evictLRUObjects(); }, description: 'Lazy cleanup and LRU eviction', }); // Medium level - pool optimization this.memoryPressureHandlers.push({ level: 'medium', priority: 3, action: async (_metrics) => { await this.optimizeObjectPools(); }, description: 'Object pool optimization', }); // Low level - background maintenance this.memoryPressureHandlers.push({ level: 'low', priority: 4, action: async (_metrics) => { await this.performBackgroundMaintenance(); }, description: 'Background maintenance', }); } private initializeBufferPools(): void { for (const size of this.memoryConfig.bufferReuse.poolSizes) { this.bufferPools.set(size, []); } } private startMonitoring(): void { this.monitoringInterval = setInterval(async () => { if (!this.isEnabled) return; try { // Check memory pressure and respond const pressureLevel = this.getCurrentMemoryPressureLevel(); await this.respondToMemoryPressure(pressureLevel); // Perform adaptive tuning if needed if (this.adaptiveTuning.enabled) { await this.performAdaptiveTuning(); } // Auto-tune object pools await this.autoTuneObjectPools(); // Record memory metrics this.performanceTracker.recordMemorySnapshot('gc-optimizer'); } catch (error) { this.emit('monitoringError', error); } }, 5000); // Every 5 seconds // Setup forced GC interval based on strategy if (this.currentStrategy.gcTuning.forcedGCInterval > 0) { this.forcedGCInterval = setInterval(async () => { if (this.shouldForceGC()) { await this.forceGarbageCollection('scheduled'); } }, this.currentStrategy.gcTuning.forcedGCInterval); } } private setupGCHooks(): void { // Hook into V8 GC events if available if (process.env.NODE_ENV !== 'production') { // Development monitoring const originalGC = global.gc; if (originalGC) { global.gc = async () => { const startTime = performance.now(); const beforeMemory = process.memoryUsage(); originalGC(); const endTime = performance.now(); const afterMemory = process.memoryUsage(); const metrics: GCMetrics = { timestamp: Date.now(), type: 'forced', duration: endTime - startTime, heapBefore: beforeMemory.heapUsed, heapAfter: afterMemory.heapUsed, heapReclaimed: beforeMemory.heapUsed - afterMemory.heapUsed, pauseTime: endTime - startTime, efficiency: (beforeMemory.heapUsed - afterMemory.heapUsed) / beforeMemory.heapUsed, triggerReason: 'manual', }; this.recordGCMetrics(metrics); }; } } } private async performLazyCleanup(): Promise<void> { // Clean up weak references in all object pools for (const pool of Array.from(this.objectPools.values())) { await pool.performMaintenanceCleanup(); } // Clean up buffer pools for (const [_size, buffers] of Array.from(this.bufferPools)) { if (buffers.length > this.memoryConfig.bufferReuse.maxBuffers * 0.8) { // Remove oldest buffers const toRemove = Math.floor(buffers.length * 0.2); buffers.splice(0, toRemove); } } } private async performAggressiveCleanup(): Promise<void> { // Force cleanup of all object pools for (const pool of Array.from(this.objectPools.values())) { await pool.forceEviction(0.5); // Evict 50% of objects } // Clear buffer pools for (const buffers of Array.from(this.bufferPools.values())) { buffers.length = 0; } // Force memory leak detector cleanup if (this.memoryLeakDetector) { await this.memoryLeakDetector.forceCleanup(); } } private async evictLRUObjects(): Promise<void> { for (const pool of Array.from(this.objectPools.values())) { await pool.evictLRU(0.2); // Evict 20% of LRU objects } } private async optimizeObjectPools(): Promise<void> { for (const pool of Array.from(this.objectPools.values())) { const stats = pool.getStatistics(); // Resize pool based on utilization if (stats.utilizationRate > 0.9) { pool.increaseSize(Math.ceil(stats.maxSize * 0.2)); } else if (stats.utilizationRate < 0.3) { pool.decreaseSize(Math.ceil(stats.maxSize * 0.1)); } } } private async performBackgroundMaintenance(): Promise<void> { // Compact object pools for (const pool of Array.from(this.objectPools.values())) { await pool.compact(); } // Analyze allocation patterns const analysis = this.analyzeAllocationPatterns(); this.emit('allocationAnalysis', analysis); } private getCurrentMemoryPressureLevel(): MemoryPressureLevel { const memoryUsage = process.memoryUsage(); const heapUsageRatio = memoryUsage.heapUsed / memoryUsage.heapTotal; if (heapUsageRatio > 0.9) return 'critical'; if (heapUsageRatio > 0.8) return 'high'; if (heapUsageRatio > 0.6) return 'medium'; return 'low'; } private async respondToMemoryPressure(level: MemoryPressureLevel): Promise<void> { const handlers = this.memoryPressureHandlers .filter(h => h.level === level) .sort((a, b) => a.priority - b.priority); for (const handler of handlers) { try { await handler.action({} as GCMetrics); this.emit('pressureHandlerExecuted', { level, handler: handler.description }); } catch (error) { this.emit('pressureHandlerError', { level, handler: handler.description, error }); } } } private async performAdaptiveTuning(): Promise<void> { const now = Date.now(); if (now - this.adaptiveTuning.lastTuningTime < this.adaptiveTuning.tuningCooldown) { return; } // Analyze recent performance const recentMetrics = this.gcMetricsHistory.slice(-10); if (recentMetrics.length < 5) return; const avgEfficiency = recentMetrics.reduce((sum, gc) => sum + gc.efficiency, 0) / recentMetrics.length; const avgDuration = recentMetrics.reduce((sum, gc) => sum + gc.duration, 0) / recentMetrics.length; // Adjust strategy based on performance if (avgEfficiency < 0.3 && avgDuration > 50) { // Poor efficiency and high duration - reduce forced GC frequency this.currentStrategy.gcTuning.forcedGCInterval *= 1.2; this.currentStrategy.gcTuning.heapUsageThreshold += 0.05; } else if (avgEfficiency > 0.7 && avgDuration < 20) { // Good efficiency and low duration - can be more aggressive this.currentStrategy.gcTuning.forcedGCInterval *= 0.9; this.currentStrategy.gcTuning.heapUsageThreshold -= 0.05; } this.adaptiveTuning.lastTuningTime = now; this.emit('adaptiveTuning', { avgEfficiency, avgDuration, strategy: this.currentStrategy }); } private async autoTuneObjectPools(): Promise<void> { for (const pool of Array.from(this.objectPools.values())) { if (pool.config.autoTune) { await pool.autoTune(); } } } private shouldForceGC(): boolean { const memoryUsage = process.memoryUsage(); const heapUsageRatio = memoryUsage.heapUsed / memoryUsage.heapTotal; return heapUsageRatio > this.currentStrategy.gcTuning.heapUsageThreshold || memoryUsage.heapUsed > this.currentStrategy.gcTuning.maxHeapSize * 1024 * 1024; } private recordGCMetrics(metrics: GCMetrics): void { this.gcMetricsHistory.push(metrics); // Keep only last 1000 GC cycles if (this.gcMetricsHistory.length > 1000) { this.gcMetricsHistory = this.gcMetricsHistory.slice(-1000); } // Record in performance tracker this.performanceTracker.recordMetric({ id: `gc-${metrics.timestamp}`, name: 'garbage-collection', category: 'memory-optimization', timestamp: metrics.timestamp, duration: metrics.duration, data: metrics as unknown as PerformanceMetricData, }); this.emit('gcMetrics', metrics); } private calculateAverageGCInterval(gcHistory: GCMetrics[]): number { if (gcHistory.length < 2) return 0; const intervals = []; for (let i = 1; i < gcHistory.length; i++) { const current = gcHistory[i]; const previous = gcHistory[i - 1]; if (current && previous) { intervals.push(current.timestamp - previous.timestamp); } } return intervals.reduce((sum, interval) => sum + interval, 0) / intervals.length; } private applyStrategy(strategy: GCOptimizationStrategy): void { // Update forced GC interval if (this.forcedGCInterval) { clearInterval(this.forcedGCInterval); } if (strategy.gcTuning.forcedGCInterval > 0) { this.forcedGCInterval = setInterval(async () => { if (this.shouldForceGC()) { await this.forceGarbageCollection('scheduled'); } }, strategy.gcTuning.forcedGCInterval); } } // Strategy creation methods private createBalancedStrategy(): GCOptimizationStrategy { return { name: 'balanced', description: 'Balanced optimization for general workloads', targetWorkloads: ['general', 'mixed'], gcTuning: { maxHeapSize: 512, heapUsageThreshold: 0.8, forcedGCInterval: 30000, incrementalGC: true, maxPauseTime: 50, }, objectLifecycle: { shortLivedThreshold: 1000, longLivedThreshold: 60000, generationalOptimization: true, }, }; } private createHighThroughputStrategy(): GCOptimizationStrategy { return { name: 'high-throughput', description: 'Optimized for maximum throughput', targetWorkloads: ['batch-processing', 'data-intensive'], gcTuning: { maxHeapSize: 1024, heapUsageThreshold: 0.9, forcedGCInterval: 60000, incrementalGC: false, maxPauseTime: 200, }, objectLifecycle: { shortLivedThreshold: 5000, longLivedThreshold: 300000, generationalOptimization: true, }, }; } private createLowLatencyStrategy(): GCOptimizationStrategy { return { name: 'low-latency', description: 'Optimized for minimal pause times', targetWorkloads: ['real-time', 'interactive'], gcTuning: { maxHeapSize: 256, heapUsageThreshold: 0.7, forcedGCInterval: 10000, incrementalGC: true, maxPauseTime: 10, }, objectLifecycle: { shortLivedThreshold: 500, longLivedThreshold: 10000, generationalOptimization: true, }, }; } private createMemoryIntensiveStrategy(): GCOptimizationStrategy { return { name: 'memory-intensive', description: 'Optimized for large memory workloads', targetWorkloads: ['large-dataset', 'caching'], gcTuning: { maxHeapSize: 2048, heapUsageThreshold: 0.85, forcedGCInterval: 45000, incrementalGC: true, maxPauseTime: 100, }, objectLifecycle: { shortLivedThreshold: 2000, longLivedThreshold: 600000, generationalOptimization: false, }, }; } private createBatchProcessingStrategy(): GCOptimizationStrategy { return { name: 'batch-processing', description: 'Optimized for batch processing workloads', targetWorkloads: ['batch', 'background-processing'], gcTuning: { maxHeapSize: 1536, heapUsageThreshold: 0.95, forcedGCInterval: 120000, incrementalGC: false, maxPauseTime: 500, }, objectLifecycle: { shortLivedThreshold: 10000, longLivedThreshold: 1800000, generationalOptimization: false, }, }; } } /** * Object Pool Implementation with Advanced Features */ export class ObjectPool<T> extends EventEmitter { public readonly config: ObjectPoolConfig; private pool: Array<{ object: T; timestamp: number; accessCount: number }> = []; private statistics = { hits: 0, misses: 0, creates: 0, destroys: 0, evictions: 0, totalAccesses: 0, }; constructor(config: ObjectPoolConfig) { super(); this.config = config; // Store performance tracker reference (may be unused in current implementation) // This allows for future performance tracking integration this.initializePool(); } /** * Get an object from the pool */ get(): T { const now = Date.now(); this.statistics.totalAccesses++; // Try to find available object for (let i = 0; i < this.pool.length; i++) { const poolItem = this.pool[i]; // Ensure poolItem exists and check TTL if configured if (!poolItem) { continue; } if (this.config.ttl && now - poolItem.timestamp > this.config.ttl) { this.pool.splice(i, 1); this.statistics.evictions++; continue; } // Validate object if validator provided if (this.config.validate && !this.config.validate(poolItem.object)) { this.pool.splice(i, 1); this.statistics.evictions++; continue; } // Found valid object this.pool.splice(i, 1); poolItem.accessCount++; this.statistics.hits++; this.emit('hit', this.getStatistics()); return poolItem.object; } // No available object - create new one this.statistics.misses++; this.statistics.creates++; const newObject = this.config.factory(); this.emit('miss', this.getStatistics()); return newObject; } /** * Return an object to the pool */ return(object: T): void { if (this.pool.length >= this.config.maxSize) { // Pool is full - evict based on strategy this.evictObject(); } // Reset object if reset function provided if (this.config.reset) { this.config.reset(object); } this.pool.push({ object, timestamp: Date.now(), accessCount: 0, }); } /** * Get pool statistics */ getStatistics(): PoolStatistics { const hitRate = this.statistics.totalAccesses > 0 ? this.statistics.hits / this.statistics.totalAccesses : 0; const utilizationRate = this.pool.length / this.config.maxSize; const averageLifetime = this.pool.length > 0 ? this.pool.reduce((sum, item) => sum + (Date.now() - item.timestamp), 0) / this.pool.length : 0; return { name: this.config.name, currentSize: this.pool.length, maxSize: this.config.maxSize, hits: this.statistics.hits, misses: this.statistics.misses, creates: this.statistics.creates, destroys: this.statistics.destroys, hitRate, utilizationRate, averageLifetime, }; } /** * Force eviction of objects */ async forceEviction(percentage: number): Promise<number> { const toEvict = Math.floor(this.pool.length * percentage); const evicted = this.pool.splice(0, toEvict); this.statistics.evictions += evicted.length; this.statistics.destroys += evicted.length; this.emit('eviction', { count: evicted.length, stats: this.getStatistics() }); return evicted.length; } /** * Evict LRU objects */ async evictLRU(percentage: number): Promise<number> { // Sort by access count and timestamp this.pool.sort((a, b) => { if (a.accessCount !== b.accessCount) { return a.accessCount - b.accessCount; } return a.timestamp - b.timestamp; }); const toEvict = Math.floor(this.pool.length * percentage); const evicted = this.pool.splice(0, toEvict); this.statistics.evictions += evicted.length; this.statistics.destroys += evicted.length; return evicted.length; } /** * Increase pool size */ increaseSize(amount: number): void { this.config.maxSize += amount; this.emit('resized', { newSize: this.config.maxSize, change: amount }); } /** * Decrease pool size */ decreaseSize(amount: number): void { this.config.maxSize = Math.max(this.config.minSize, this.config.maxSize - amount); // Evict excess objects if needed if (this.pool.length > this.config.maxSize) { const excess = this.pool.length - this.config.maxSize; this.forceEviction(excess / this.pool.length); } this.emit('resized', { newSize: this.config.maxSize, change: -amount }); } /** * Compact pool by removing invalid objects */ async compact(): Promise<number> { const before = this.pool.length; const now = Date.now(); this.pool = this.pool.filter(item => { // Check TTL if (this.config.ttl && now - item.timestamp > this.config.ttl) { return false; } // Check validation if (this.config.validate && !this.config.validate(item.object)) { return false; } return true; }); const removed = before - this.pool.length; this.statistics.evictions += removed; this.statistics.destroys += removed; return removed; } /** * Auto-tune pool size based on usage patterns */ async autoTune(): Promise<void> { const stats = this.getStatistics(); // Increase size if hit rate is low and utilization is high if (stats.hitRate < 0.7 && stats.utilizationRate > 0.9) { this.increaseSize(Math.ceil(this.config.maxSize * 0.1)); } // Decrease size if utilization is consistently low if (stats.utilizationRate < 0.3 && this.pool.length > this.config.minSize) { this.decreaseSize(Math.ceil(this.config.maxSize * 0.05)); } } /** * Perform maintenance cleanup */ async performMaintenanceCleanup(): Promise<void> { await this.compact(); } /** * Shutdown pool */ shutdown(): void { this.pool.length = 0; this.removeAllListeners(); } // Private Methods private initializePool(): void { // Pre-populate pool with minimum objects for (let i = 0; i < this.config.minSize; i++) { this.pool.push({ object: this.config.factory(), timestamp: Date.now(), accessCount: 0, }); this.statistics.creates++; } } private evictObject(): void { if (this.pool.length === 0) return; let indexToEvict = 0; switch (this.config.evictionStrategy) { case 'lru': // Find least recently used let oldestTime = this.pool[0]?.timestamp || 0; for (let i = 1; i < this.pool.length; i++) { const item = this.pool[i]; if (item && item.timestamp < oldestTime) { oldestTime = item.timestamp; indexToEvict = i; } } break; case 'fifo': // Remove first (oldest) indexToEvict = 0; break; case 'random': // Remove random indexToEvict = Math.floor(Math.random() * this.pool.length); break; case 'ttl': // Find expired or oldest const now = Date.now(); for (let i = 0; i < this.pool.length; i++) { const item = this.pool[i]; if (item && this.config.ttl && now - item.timestamp > this.config.ttl) { indexToEvict = i; break; } } break; } this.pool.splice(indexToEvict, 1); this.statistics.evictions++; this.statistics.destroys++; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sloth-wq/prompt-auto-optimizer-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server