Files
esengine/packages/core/src/Utils/Pool/PoolManager.ts

236 lines
6.0 KiB
TypeScript
Raw Normal View History

import { IPoolable, PoolStats } from './IPoolable';
import { Pool } from './Pool';
import type { IService } from '../../Core/ServiceContainer';
/**
*
*
*/
export class PoolManager implements IService {
private pools = new Map<string, Pool<any>>();
private autoCompactInterval = 60000; // 60秒
private lastCompactTime = 0;
constructor() {
// 普通构造函数,不再使用单例模式
}
/**
*
* @param name
* @param pool
*/
public registerPool<T extends IPoolable>(name: string, pool: Pool<T>): void {
this.pools.set(name, pool);
}
/**
*
* @param name
* @returns
*/
public getPool<T extends IPoolable>(name: string): Pool<T> | null {
return this.pools.get(name) || null;
}
/**
*
*/
public update(): void {
const now = Date.now();
if (now - this.lastCompactTime > this.autoCompactInterval) {
this.compactAllPools();
this.lastCompactTime = now;
}
}
/**
*
* @param name
* @param createFn
* @param maxSize
* @param estimatedObjectSize
* @returns
*/
public createPool<T extends IPoolable>(
name: string,
createFn: () => T,
maxSize: number = 100,
estimatedObjectSize: number = 1024
): Pool<T> {
let pool = this.pools.get(name) as Pool<T>;
if (!pool) {
pool = new Pool(createFn, maxSize, estimatedObjectSize);
this.pools.set(name, pool);
}
return pool;
}
/**
*
* @param name
* @returns
*/
public removePool(name: string): boolean {
const pool = this.pools.get(name);
if (pool) {
pool.clear();
this.pools.delete(name);
return true;
}
return false;
}
/**
*
* @returns
*/
public getPoolNames(): string[] {
return Array.from(this.pools.keys());
}
/**
*
* @returns
*/
public getPoolCount(): number {
return this.pools.size;
}
/**
*
*/
public compactAllPools(): void {
for (const pool of this.pools.values()) {
pool.compact();
}
}
/**
*
*/
public clearAllPools(): void {
for (const pool of this.pools.values()) {
pool.clear();
}
}
/**
*
* @returns
*/
public getAllStats(): Map<string, PoolStats> {
const stats = new Map<string, PoolStats>();
for (const [name, pool] of this.pools) {
stats.set(name, pool.getStats());
}
return stats;
}
/**
*
* @returns
*/
public getGlobalStats(): PoolStats {
let totalSize = 0;
let totalMaxSize = 0;
let totalCreated = 0;
let totalObtained = 0;
let totalReleased = 0;
let totalMemoryUsage = 0;
for (const pool of this.pools.values()) {
const stats = pool.getStats();
totalSize += stats.size;
totalMaxSize += stats.maxSize;
totalCreated += stats.totalCreated;
totalObtained += stats.totalObtained;
totalReleased += stats.totalReleased;
totalMemoryUsage += stats.estimatedMemoryUsage;
}
const hitRate = totalObtained === 0 ? 0 : (totalObtained - totalCreated) / totalObtained;
return {
size: totalSize,
maxSize: totalMaxSize,
totalCreated,
totalObtained,
totalReleased,
hitRate,
estimatedMemoryUsage: totalMemoryUsage
};
}
/**
*
* @returns
*/
public getStatsString(): string {
const lines: string[] = ['=== Pool Manager Statistics ===', ''];
if (this.pools.size === 0) {
lines.push('No pools registered');
return lines.join('\n');
}
const globalStats = this.getGlobalStats();
lines.push(`Total Pools: ${this.pools.size}`);
lines.push(`Global Hit Rate: ${(globalStats.hitRate * 100).toFixed(1)}%`);
lines.push(`Global Memory Usage: ${(globalStats.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
lines.push('');
for (const [name, pool] of this.pools) {
const stats = pool.getStats();
lines.push(`${name}:`);
lines.push(` Size: ${stats.size}/${stats.maxSize}`);
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
lines.push(` Memory: ${(stats.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
lines.push('');
}
return lines.join('\n');
}
/**
*
* @param intervalMs
*/
public setAutoCompactInterval(intervalMs: number): void {
this.autoCompactInterval = intervalMs;
}
/**
*
*/
public prewarmAllPools(): void {
for (const pool of this.pools.values()) {
const stats = pool.getStats();
const prewarmCount = Math.floor(stats.maxSize * 0.2); // 预填充20%
pool.prewarm(prewarmCount);
}
}
/**
*
*/
public reset(): void {
this.clearAllPools();
this.pools.clear();
this.lastCompactTime = 0;
}
/**
*
* IService
*/
public dispose(): void {
this.reset();
}
}