fortify2-js
Version:
MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.
357 lines (353 loc) • 10.7 kB
JavaScript
'use strict';
var types = require('./types.js');
/**
* Advanced Memory Pool Implementation
*
* Provides efficient object pooling with multiple strategies and comprehensive monitoring
*/
/**
* Advanced memory pool with multiple strategies and monitoring
*/
class AdvancedMemoryPool {
constructor(config, eventManager) {
this.items = [];
this.config = config;
this.eventManager = eventManager;
this.stats = {
totalAcquisitions: 0,
totalReleases: 0,
hits: 0,
misses: 0,
createdAt: Date.now(),
lastUsed: Date.now(),
};
this.eventManager.emit(types.MemoryEventType.POOL_CREATED, {
name: config.name,
strategy: config.strategy,
capacity: config.capacity,
});
}
/**
* Acquire an item from the pool
*/
acquire() {
this.stats.totalAcquisitions++;
this.stats.lastUsed = Date.now();
// Try to get an item from the pool
const poolItem = this.getItemFromPool();
if (poolItem) {
this.stats.hits++;
poolItem.lastUsed = Date.now();
poolItem.usageCount++;
// Call onAcquire callback if provided
this.config.onAcquire?.(poolItem.item);
return poolItem.item;
}
else {
// Create new item
this.stats.misses++;
const newItem = this.config.factory();
// Call onAcquire callback if provided
this.config.onAcquire?.(newItem);
return newItem;
}
}
/**
* Release an item back to the pool
*/
release(item) {
this.stats.totalReleases++;
this.stats.lastUsed = Date.now();
// Validate item if validator is provided
if (this.config.validator && !this.config.validator(item)) {
return; // Don't add invalid items to pool
}
// Check if pool has capacity
if (this.items.length >= this.config.capacity) {
// Pool is full, apply strategy to make room
this.makeRoom();
}
// Reset the item
try {
this.config.reset(item);
}
catch (error) {
this.eventManager.emit(types.MemoryEventType.ERROR_OCCURRED, {
error: `Failed to reset item in pool ${this.config.name}: ${error}`,
poolName: this.config.name,
});
return; // Don't add item that failed to reset
}
// Create pool item wrapper
const poolItem = {
item,
createdAt: Date.now(),
lastUsed: Date.now(),
usageCount: 0,
};
// Add to pool based on strategy
this.addItemToPool(poolItem);
// Call onRelease callback if provided
this.config.onRelease?.(item);
}
/**
* Get item from pool based on strategy
*/
getItemFromPool() {
if (this.items.length === 0) {
return null;
}
// Remove expired items first
this.removeExpiredItems();
if (this.items.length === 0) {
return null;
}
switch (this.config.strategy) {
case types.PoolStrategy.LIFO:
return this.items.pop() || null;
case types.PoolStrategy.FIFO:
return this.items.shift() || null;
case types.PoolStrategy.LRU:
return this.getLRUItem();
case types.PoolStrategy.ADAPTIVE:
return this.getAdaptiveItem();
default:
return this.items.pop() || null;
}
}
/**
* Add item to pool based on strategy
*/
addItemToPool(poolItem) {
switch (this.config.strategy) {
case types.PoolStrategy.LIFO:
this.items.push(poolItem);
break;
case types.PoolStrategy.FIFO:
this.items.unshift(poolItem);
break;
case types.PoolStrategy.LRU:
case types.PoolStrategy.ADAPTIVE:
// For LRU and adaptive, add to end (most recently used)
this.items.push(poolItem);
break;
default:
this.items.push(poolItem);
}
}
/**
* Get least recently used item
*/
getLRUItem() {
if (this.items.length === 0)
return null;
// Find item with oldest lastUsed timestamp
let lruIndex = 0;
let oldestTime = this.items[0].lastUsed;
for (let i = 1; i < this.items.length; i++) {
if (this.items[i].lastUsed < oldestTime) {
oldestTime = this.items[i].lastUsed;
lruIndex = i;
}
}
return this.items.splice(lruIndex, 1)[0];
}
/**
* Get item using adaptive strategy
*/
getAdaptiveItem() {
if (this.items.length === 0)
return null;
const hitRate = this.getHitRate();
// If hit rate is high, prefer LIFO (better cache locality)
// If hit rate is low, prefer LRU (better memory efficiency)
if (hitRate > 0.8) {
return this.items.pop() || null;
}
else {
return this.getLRUItem();
}
}
/**
* Make room in the pool when it's full
*/
makeRoom() {
if (this.items.length === 0)
return;
switch (this.config.strategy) {
case types.PoolStrategy.LIFO:
this.items.shift(); // Remove oldest
break;
case types.PoolStrategy.FIFO:
this.items.pop(); // Remove newest
break;
case types.PoolStrategy.LRU:
this.getLRUItem(); // Remove least recently used
break;
case types.PoolStrategy.ADAPTIVE:
// Remove based on current performance
const hitRate = this.getHitRate();
if (hitRate > 0.8) {
this.items.shift(); // Remove oldest
}
else {
this.getLRUItem(); // Remove LRU
}
break;
}
}
/**
* Remove expired items from the pool
*/
removeExpiredItems() {
if (!this.config.maxAge)
return;
const now = Date.now();
const maxAge = this.config.maxAge;
this.items = this.items.filter((poolItem) => {
const age = now - poolItem.createdAt;
return age <= maxAge;
});
}
/**
* Clear all items from the pool
*/
clear() {
this.items = [];
this.eventManager.emit(types.MemoryEventType.POOL_DESTROYED, {
name: this.config.name,
reason: "cleared",
});
}
/**
* Resize the pool capacity
*/
resize(newCapacity) {
if (newCapacity < 0) {
throw new Error("Pool capacity cannot be negative");
}
const oldCapacity = this.config.capacity;
this.config.capacity = newCapacity;
// If new capacity is smaller, remove excess items
while (this.items.length > newCapacity) {
this.makeRoom();
}
this.eventManager.emit(types.MemoryEventType.CONFIG_UPDATED, {
poolName: this.config.name,
capacityChange: {
from: oldCapacity,
to: newCapacity,
},
});
}
/**
* Get pool statistics
*/
getStats() {
return {
name: this.config.name,
size: this.items.length,
capacity: this.config.capacity,
hitRate: this.getHitRate(),
totalAcquisitions: this.stats.totalAcquisitions,
totalReleases: this.stats.totalReleases,
strategy: this.config.strategy,
createdAt: this.stats.createdAt,
lastUsed: this.stats.lastUsed,
};
}
/**
* Calculate hit rate
*/
getHitRate() {
const total = this.stats.hits + this.stats.misses;
return total > 0 ? this.stats.hits / total : 0;
}
/**
* Get current pool size
*/
get size() {
return this.items.length;
}
/**
* Get pool capacity
*/
get capacity() {
return this.config.capacity;
}
/**
* Get pool strategy
*/
get strategy() {
return this.config.strategy;
}
/**
* Get pool name
*/
get name() {
return this.config.name;
}
/**
* Get detailed pool information for debugging
*/
getDebugInfo() {
return {
config: {
name: this.config.name,
capacity: this.config.capacity,
strategy: this.config.strategy,
maxAge: this.config.maxAge,
},
stats: this.getStats(),
items: this.items.map((item) => ({
createdAt: item.createdAt,
lastUsed: item.lastUsed,
usageCount: item.usageCount,
age: Date.now() - item.createdAt,
})),
performance: {
hitRate: this.getHitRate(),
efficiency: this.items.length / this.config.capacity,
averageAge: this.getAverageItemAge(),
},
};
}
/**
* Get average age of items in the pool
*/
getAverageItemAge() {
if (this.items.length === 0)
return 0;
const now = Date.now();
const totalAge = this.items.reduce((sum, item) => sum + (now - item.createdAt), 0);
return totalAge / this.items.length;
}
/**
* Update pool configuration
*/
updateConfig(updates) {
// Update configuration
this.config = { ...this.config, ...updates };
// Handle capacity changes
if (updates.capacity !== undefined) {
this.resize(updates.capacity);
}
this.eventManager.emit(types.MemoryEventType.CONFIG_UPDATED, {
poolName: this.config.name,
updates,
});
}
/**
* Destroy the pool and clean up resources
*/
destroy() {
this.clear();
this.eventManager.emit(types.MemoryEventType.POOL_DESTROYED, {
name: this.config.name,
reason: "destroyed",
finalStats: this.getStats(),
});
}
}
exports.AdvancedMemoryPool = AdvancedMemoryPool;
//# sourceMappingURL=memory-pool.js.map