UNPKG

qnce-engine

Version:

Core QNCE (Quantum Narrative Convergence Engine) - Framework agnostic narrative engine with performance optimization

297 lines 7.71 kB
"use strict"; // S2-T1: Object Pooling for Narrative Objects // Generic object pool to eliminate runtime allocations and reduce GC pressure Object.defineProperty(exports, "__esModule", { value: true }); exports.poolManager = exports.PoolManager = exports.PooledAsset = exports.PooledNode = exports.PooledFlow = exports.ObjectPool = void 0; /** * Generic Object Pool for QNCE narrative objects * Reduces GC pressure by reusing objects instead of creating new ones */ class ObjectPool { pool = []; createFn; maxSize; created = 0; borrowed = 0; returned = 0; constructor(createFn, initialSize = 10, maxSize = 100) { this.createFn = createFn; this.maxSize = maxSize; // Pre-populate pool for (let i = 0; i < initialSize; i++) { const obj = this.createFn(); obj.setInUse(false); this.pool.push(obj); this.created++; } } /** * Borrow an object from the pool */ borrow() { let obj; if (this.pool.length > 0) { obj = this.pool.pop(); } else { // Pool exhausted, create new object obj = this.createFn(); this.created++; } obj.reset(); obj.setInUse(true); this.borrowed++; return obj; } /** * Return an object to the pool */ return(obj) { if (!obj.isInUse()) { console.warn('Attempting to return object that is not in use'); return; } obj.setInUse(false); this.returned++; // Only return to pool if under max size if (this.pool.length < this.maxSize) { this.pool.push(obj); } // Otherwise let GC handle it (controlled disposal) } /** * Get pool statistics for monitoring */ getStats() { return { poolSize: this.pool.length, maxSize: this.maxSize, created: this.created, borrowed: this.borrowed, returned: this.returned, inUse: this.borrowed - this.returned, hitRate: this.borrowed > 0 ? ((this.borrowed - this.created) / this.borrowed) * 100 : 0 }; } /** * Clear the pool (useful for testing) */ clear() { this.pool.forEach(obj => obj.setInUse(false)); this.pool.length = 0; this.created = 0; this.borrowed = 0; this.returned = 0; } /** * Resize the pool */ resize(newSize) { if (newSize < this.pool.length) { // Shrink pool this.pool.splice(newSize); } else if (newSize > this.pool.length) { // Grow pool const toAdd = newSize - this.pool.length; for (let i = 0; i < toAdd && this.pool.length < this.maxSize; i++) { const obj = this.createFn(); obj.setInUse(false); this.pool.push(obj); this.created++; } } } } exports.ObjectPool = ObjectPool; /** * Pooled Flow object for narrative state management */ class PooledFlow { _inUse = false; nodeId = ''; timestamp = 0; metadata = {}; transitions = []; constructor() { this.reset(); } reset() { this.nodeId = ''; this.timestamp = 0; this.metadata = {}; this.transitions.length = 0; } isInUse() { return this._inUse; } setInUse(inUse) { this._inUse = inUse; } // Flow-specific methods initialize(nodeId, metadata) { this.nodeId = nodeId; this.timestamp = performance.now(); if (metadata) { this.metadata = { ...metadata }; } } addTransition(fromNodeId, toNodeId) { this.transitions.push(`${fromNodeId}->${toNodeId}`); } getDuration() { return performance.now() - this.timestamp; } } exports.PooledFlow = PooledFlow; /** * Pooled Node object for narrative content */ class PooledNode { _inUse = false; id = ''; text = ''; choices = []; flags = {}; lastAccessed = 0; constructor() { this.reset(); } reset() { this.id = ''; this.text = ''; this.choices.length = 0; this.flags = {}; this.lastAccessed = 0; } isInUse() { return this._inUse; } setInUse(inUse) { this._inUse = inUse; } // Node-specific methods initialize(id, text, choices = []) { this.id = id; this.text = text; this.choices = [...choices]; this.lastAccessed = performance.now(); } touch() { this.lastAccessed = performance.now(); } } exports.PooledNode = PooledNode; /** * Pooled Asset object for narrative resources */ class PooledAsset { _inUse = false; id = ''; type = ''; data = null; size = 0; loaded = false; constructor() { this.reset(); } reset() { this.id = ''; this.type = ''; this.data = null; this.size = 0; this.loaded = false; } isInUse() { return this._inUse; } setInUse(inUse) { this._inUse = inUse; } // Asset-specific methods initialize(id, type, data) { this.id = id; this.type = type; this.data = data; this.size = this.calculateSize(data); this.loaded = true; } calculateSize(data) { if (typeof data === 'string') { return data.length * 2; // Approximate UTF-16 size } if (data && typeof data === 'object') { return JSON.stringify(data).length * 2; } return 0; } } exports.PooledAsset = PooledAsset; /** * Pool Manager - Centralized management of all object pools */ class PoolManager { static instance; flowPool; nodePool; assetPool; constructor() { // Initialize pools with different sizes based on expected usage this.flowPool = new ObjectPool(() => new PooledFlow(), 5, 50); this.nodePool = new ObjectPool(() => new PooledNode(), 20, 200); this.assetPool = new ObjectPool(() => new PooledAsset(), 10, 100); } static getInstance() { if (!PoolManager.instance) { PoolManager.instance = new PoolManager(); } return PoolManager.instance; } // Flow pool methods borrowFlow() { return this.flowPool.borrow(); } returnFlow(flow) { this.flowPool.return(flow); } // Node pool methods borrowNode() { return this.nodePool.borrow(); } returnNode(node) { this.nodePool.return(node); } // Asset pool methods borrowAsset() { return this.assetPool.borrow(); } returnAsset(asset) { this.assetPool.return(asset); } // Statistics and monitoring getAllStats() { return { flows: this.flowPool.getStats(), nodes: this.nodePool.getStats(), assets: this.assetPool.getStats() }; } // Performance monitoring getGCPressureReduction() { const stats = this.getAllStats(); const totalHitRate = (stats.flows.hitRate + stats.nodes.hitRate + stats.assets.hitRate) / 3; return totalHitRate; } // Cleanup for testing clearAllPools() { this.flowPool.clear(); this.nodePool.clear(); this.assetPool.clear(); } } exports.PoolManager = PoolManager; // Export singleton instance exports.poolManager = PoolManager.getInstance(); //# sourceMappingURL=ObjectPool.js.map