项目统一改用Logger控制管理

拆分pool类和FluentAPI
This commit is contained in:
YHH
2025-08-08 11:16:00 +08:00
parent 2d389308ea
commit 87dd564a12
51 changed files with 1813 additions and 1491 deletions

View File

@@ -0,0 +1,310 @@
/**
* 日志级别
*/
export enum LogLevel {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
Fatal = 4,
None = 5
}
/**
* 日志接口
*/
export interface ILogger {
debug(message: string, ...args: unknown[]): void;
info(message: string, ...args: unknown[]): void;
warn(message: string, ...args: unknown[]): void;
error(message: string, ...args: unknown[]): void;
fatal(message: string, ...args: unknown[]): void;
}
/**
* 日志配置
*/
export interface LoggerConfig {
/** 日志级别 */
level: LogLevel;
/** 是否启用时间戳 */
enableTimestamp: boolean;
/** 是否启用颜色 */
enableColors: boolean;
/** 日志前缀 */
prefix?: string;
/** 自定义输出函数 */
output?: (level: LogLevel, message: string) => void;
}
/**
* 默认控制台日志实现
*/
export class ConsoleLogger implements ILogger {
private _config: LoggerConfig;
constructor(config: Partial<LoggerConfig> = {}) {
this._config = {
level: LogLevel.Info,
enableTimestamp: true,
enableColors: typeof window === 'undefined',
...config
};
}
/**
* 输出调试级别日志
* @param message 日志消息
* @param args 附加参数
*/
public debug(message: string, ...args: unknown[]): void {
this.log(LogLevel.Debug, message, ...args);
}
/**
* 输出信息级别日志
* @param message 日志消息
* @param args 附加参数
*/
public info(message: string, ...args: unknown[]): void {
this.log(LogLevel.Info, message, ...args);
}
/**
* 输出警告级别日志
* @param message 日志消息
* @param args 附加参数
*/
public warn(message: string, ...args: unknown[]): void {
this.log(LogLevel.Warn, message, ...args);
}
/**
* 输出错误级别日志
* @param message 日志消息
* @param args 附加参数
*/
public error(message: string, ...args: unknown[]): void {
this.log(LogLevel.Error, message, ...args);
}
/**
* 输出致命错误级别日志
* @param message 日志消息
* @param args 附加参数
*/
public fatal(message: string, ...args: unknown[]): void {
this.log(LogLevel.Fatal, message, ...args);
}
/**
* 设置日志级别
* @param level 日志级别
*/
public setLevel(level: LogLevel): void {
this._config.level = level;
}
/**
* 设置日志前缀
* @param prefix 前缀字符串
*/
public setPrefix(prefix: string): void {
this._config.prefix = prefix;
}
/**
* 内部日志输出方法
* @param level 日志级别
* @param message 日志消息
* @param args 附加参数
*/
private log(level: LogLevel, message: string, ...args: unknown[]): void {
if (level < this._config.level) {
return;
}
let formattedMessage = message;
// 添加时间戳
if (this._config.enableTimestamp) {
const timestamp = new Date().toISOString();
formattedMessage = `[${timestamp}] ${formattedMessage}`;
}
// 添加前缀
if (this._config.prefix) {
formattedMessage = `[${this._config.prefix}] ${formattedMessage}`;
}
// 添加日志级别
const levelName = LogLevel[level].toUpperCase();
formattedMessage = `[${levelName}] ${formattedMessage}`;
// 使用自定义输出或默认控制台输出
if (this._config.output) {
this._config.output(level, formattedMessage);
} else {
this.outputToConsole(level, formattedMessage, ...args);
}
}
/**
* 输出到控制台
* @param level 日志级别
* @param message 格式化后的消息
* @param args 附加参数
*/
private outputToConsole(level: LogLevel, message: string, ...args: unknown[]): void {
const colors = this._config.enableColors ? this.getColors() : null;
switch (level) {
case LogLevel.Debug:
if (colors) {
console.debug(`${colors.gray}${message}${colors.reset}`, ...args);
} else {
console.debug(message, ...args);
}
break;
case LogLevel.Info:
if (colors) {
console.info(`${colors.blue}${message}${colors.reset}`, ...args);
} else {
console.info(message, ...args);
}
break;
case LogLevel.Warn:
if (colors) {
console.warn(`${colors.yellow}${message}${colors.reset}`, ...args);
} else {
console.warn(message, ...args);
}
break;
case LogLevel.Error:
case LogLevel.Fatal:
if (colors) {
console.error(`${colors.red}${message}${colors.reset}`, ...args);
} else {
console.error(message, ...args);
}
break;
}
}
/**
* 获取控制台颜色配置
* @returns 颜色配置对象
*/
private getColors() {
return {
reset: '\x1b[0m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
gray: '\x1b[90m'
};
}
}
/**
* 日志管理器
*/
export class LoggerManager {
private static _instance: LoggerManager;
private _loggers = new Map<string, ILogger>();
private _defaultLogger: ILogger;
private constructor() {
this._defaultLogger = new ConsoleLogger();
}
/**
* 获取日志管理器实例
* @returns 日志管理器实例
*/
public static getInstance(): LoggerManager {
if (!LoggerManager._instance) {
LoggerManager._instance = new LoggerManager();
}
return LoggerManager._instance;
}
/**
* 获取或创建日志器
* @param name 日志器名称
* @returns 日志器实例
*/
public getLogger(name?: string): ILogger {
if (!name) {
return this._defaultLogger;
}
if (!this._loggers.has(name)) {
const logger = new ConsoleLogger({
prefix: name,
level: LogLevel.Info
});
this._loggers.set(name, logger);
}
return this._loggers.get(name)!;
}
/**
* 设置日志器
* @param name 日志器名称
* @param logger 日志器实例
*/
public setLogger(name: string, logger: ILogger): void {
this._loggers.set(name, logger);
}
/**
* 设置全局日志级别
* @param level 日志级别
*/
public setGlobalLevel(level: LogLevel): void {
if (this._defaultLogger instanceof ConsoleLogger) {
this._defaultLogger.setLevel(level);
}
for (const logger of this._loggers.values()) {
if (logger instanceof ConsoleLogger) {
logger.setLevel(level);
}
}
}
/**
* 创建子日志器
* @param parentName 父日志器名称
* @param childName 子日志器名称
* @returns 子日志器实例
*/
public createChildLogger(parentName: string, childName: string): ILogger {
const fullName = `${parentName}.${childName}`;
return this.getLogger(fullName);
}
}
/**
* 默认日志器实例
*/
export const Logger = LoggerManager.getInstance().getLogger();
/**
* 创建命名日志器
* @param name 日志器名称
* @returns 日志器实例
*/
export function createLogger(name: string): ILogger {
return LoggerManager.getInstance().getLogger(name);
}
/**
* 设置全局日志级别
* @param level 日志级别
*/
export function setGlobalLogLevel(level: LogLevel): void {
LoggerManager.getInstance().setGlobalLevel(level);
}

View File

@@ -1,565 +0,0 @@
/**
* 可池化对象接口
*/
export interface IPoolable {
/**
* 重置对象状态,准备重用
*/
reset(): void;
}
/**
* 对象池统计信息
*/
export interface PoolStats {
/** 池中对象数量 */
size: number;
/** 池的最大大小 */
maxSize: number;
/** 总共创建的对象数量 */
totalCreated: number;
/** 总共获取的次数 */
totalObtained: number;
/** 总共释放的次数 */
totalReleased: number;
/** 命中率(从池中获取的比例) */
hitRate: number;
/** 内存使用估算(字节) */
estimatedMemoryUsage: number;
}
/**
* 高性能通用对象池
* 支持任意类型的对象池化,包含详细的统计信息
*/
export class Pool<T extends IPoolable> {
private static _pools = new Map<Function, Pool<any>>();
private _objects: T[] = [];
private _createFn: () => T;
private _maxSize: number;
private _stats: PoolStats;
private _objectSize: number; // 估算的单个对象大小
/**
* 构造函数
* @param createFn 创建对象的函数
* @param maxSize 池的最大大小默认100
* @param estimatedObjectSize 估算的单个对象大小字节默认1024
*/
constructor(createFn: () => T, maxSize: number = 100, estimatedObjectSize: number = 1024) {
this._createFn = createFn;
this._maxSize = maxSize;
this._objectSize = estimatedObjectSize;
this._stats = {
size: 0,
maxSize,
totalCreated: 0,
totalObtained: 0,
totalReleased: 0,
hitRate: 0,
estimatedMemoryUsage: 0
};
}
/**
* 获取指定类型的对象池
* @param type 对象类型
* @param maxSize 池的最大大小
* @param estimatedObjectSize 估算的单个对象大小
* @returns 对象池实例
*/
public static getPool<T extends IPoolable>(
type: new (...args: unknown[]) => T,
maxSize: number = 100,
estimatedObjectSize: number = 1024
): Pool<T> {
let pool = this._pools.get(type);
if (!pool) {
pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize);
this._pools.set(type, pool);
}
return pool;
}
/**
* 从池中获取对象
* @returns 对象实例
*/
public obtain(): T {
this._stats.totalObtained++;
if (this._objects.length > 0) {
const obj = this._objects.pop()!;
this._stats.size--;
this._updateHitRate();
this._updateMemoryUsage();
return obj;
}
// 池中没有对象,创建新的
const obj = this._createFn();
this._stats.totalCreated++;
this._updateHitRate();
return obj;
}
/**
* 将对象归还到池中
* @param obj 要归还的对象
*/
public free(obj: T): void {
if (this._objects.length < this._maxSize) {
obj.reset();
this._objects.push(obj);
this._stats.size++;
this._stats.totalReleased++;
this._updateMemoryUsage();
}
// 如果池已满对象会被丢弃由GC回收
}
/**
* 预热池,创建指定数量的对象
* @param count 要创建的对象数量
*/
public warmUp(count: number): void {
const targetSize = Math.min(count, this._maxSize);
while (this._objects.length < targetSize) {
const obj = this._createFn();
this._stats.totalCreated++;
this._objects.push(obj);
this._stats.size++;
}
this._updateMemoryUsage();
}
/**
* 清空池
*/
public clear(): void {
this._objects.length = 0;
this._stats.size = 0;
this._updateMemoryUsage();
}
/**
* 获取池中对象数量
*/
public get size(): number {
return this._objects.length;
}
/**
* 获取池的最大大小
*/
public get maxSize(): number {
return this._maxSize;
}
/**
* 设置池的最大大小
*/
public set maxSize(value: number) {
this._maxSize = value;
this._stats.maxSize = value;
// 如果当前池大小超过新的最大值,则移除多余的对象
while (this._objects.length > this._maxSize) {
this._objects.pop();
this._stats.size--;
}
this._updateMemoryUsage();
}
/**
* 获取池的统计信息
*/
public getStats(): PoolStats {
return { ...this._stats };
}
/**
* 重置统计信息
*/
public resetStats(): void {
this._stats.totalCreated = 0;
this._stats.totalObtained = 0;
this._stats.totalReleased = 0;
this._stats.hitRate = 0;
}
/**
* 更新命中率
*/
private _updateHitRate(): void {
if (this._stats.totalObtained > 0) {
const hits = this._stats.totalObtained - this._stats.totalCreated;
this._stats.hitRate = hits / this._stats.totalObtained;
}
}
/**
* 更新内存使用估算
*/
private _updateMemoryUsage(): void {
this._stats.estimatedMemoryUsage = this._stats.size * this._objectSize;
}
/**
* 静态方法:从指定类型的池中获取对象
* @param type 对象类型
* @returns 对象实例
*/
public static obtain<T extends IPoolable>(type: new (...args: unknown[]) => T): T {
return this.getPool(type).obtain();
}
/**
* 静态方法:将对象归还到对应类型的池中
* @param type 对象类型
* @param obj 要归还的对象
*/
public static free<T extends IPoolable>(type: new (...args: unknown[]) => T, obj: T): void {
this.getPool(type).free(obj);
}
/**
* 静态方法:预热指定类型的池
* @param type 对象类型
* @param count 要创建的对象数量
*/
public static warmUp<T extends IPoolable>(type: new (...args: unknown[]) => T, count: number): void {
this.getPool(type).warmUp(count);
}
/**
* 静态方法:清空指定类型的池
* @param type 对象类型
*/
public static clearPool<T extends IPoolable>(type: new (...args: unknown[]) => T): void {
const pool = this._pools.get(type);
if (pool) {
pool.clear();
}
}
/**
* 静态方法:清空所有池
*/
public static clearAllPools(): void {
for (const pool of this._pools.values()) {
pool.clear();
}
this._pools.clear();
}
/**
* 静态方法:获取池的统计信息
* @returns 池的统计信息
*/
public static getStats(): { [typeName: string]: PoolStats } {
const stats: { [typeName: string]: PoolStats } = {};
for (const [type, pool] of this._pools.entries()) {
const typeName = (type as any).name || 'Unknown';
stats[typeName] = pool.getStats();
}
return stats;
}
/**
* 静态方法:获取所有池的总内存使用量
* @returns 总内存使用量(字节)
*/
public static getTotalMemoryUsage(): number {
let total = 0;
for (const pool of this._pools.values()) {
total += pool.getStats().estimatedMemoryUsage;
}
return total;
}
/**
* 静态方法:获取性能报告
* @returns 格式化的性能报告
*/
public static getPerformanceReport(): string {
const stats = this.getStats();
const lines: string[] = [];
lines.push('=== Object Pool Performance Report ===');
lines.push(`Total Memory Usage: ${(this.getTotalMemoryUsage() / 1024 / 1024).toFixed(2)} MB`);
lines.push('');
for (const [typeName, stat] of Object.entries(stats)) {
lines.push(`${typeName}:`);
lines.push(` Size: ${stat.size}/${stat.maxSize}`);
lines.push(` Hit Rate: ${(stat.hitRate * 100).toFixed(1)}%`);
lines.push(` Total Created: ${stat.totalCreated}`);
lines.push(` Total Obtained: ${stat.totalObtained}`);
lines.push(` Memory: ${(stat.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
lines.push('');
}
return lines.join('\n');
}
}
/**
* 分层对象池
* 使用多个不同大小的池来优化内存使用
*/
export class TieredObjectPool<T extends IPoolable> {
private pools: Pool<T>[] = [];
private createFn: () => T;
private resetFn: (obj: T) => void;
private tierSizes: number[];
private totalObtained = 0;
private totalReleased = 0;
/**
* 构造函数
* @param createFn 创建对象的函数
* @param resetFn 重置对象的函数
* @param tierSizes 各层级的大小,默认[10, 50, 200]
* @param estimatedObjectSize 估算的单个对象大小
*/
constructor(
createFn: () => T,
resetFn: (obj: T) => void,
tierSizes: number[] = [10, 50, 200],
estimatedObjectSize: number = 1024
) {
this.createFn = createFn;
this.resetFn = resetFn;
this.tierSizes = tierSizes;
// 初始化不同层级的池
for (const size of tierSizes) {
this.pools.push(new Pool(createFn, size, estimatedObjectSize));
}
}
/**
* 获取对象
* @returns 对象实例
*/
public obtain(): T {
this.totalObtained++;
// 从最小的池开始尝试获取
for (const pool of this.pools) {
if (pool.size > 0) {
return pool.obtain();
}
}
// 所有池都空了,创建新对象
return this.createFn();
}
/**
* 释放对象
* @param obj 要释放的对象
*/
public release(obj: T): void {
this.totalReleased++;
this.resetFn(obj);
// 放入第一个有空间的池
for (const pool of this.pools) {
if (pool.size < pool.maxSize) {
pool.free(obj);
return;
}
}
// 所有池都满了,直接丢弃
}
/**
* 预热所有池
* @param totalCount 总预热数量
*/
public warmUp(totalCount: number): void {
let remaining = totalCount;
for (const pool of this.pools) {
const warmUpCount = Math.min(remaining, pool.maxSize);
pool.warmUp(warmUpCount);
remaining -= warmUpCount;
if (remaining <= 0) break;
}
}
/**
* 清空所有池
*/
public clear(): void {
for (const pool of this.pools) {
pool.clear();
}
}
/**
* 获取统计信息
*/
public getStats(): {
totalSize: number;
totalMaxSize: number;
totalMemoryUsage: number;
tierStats: PoolStats[];
hitRate: number;
} {
let totalSize = 0;
let totalMaxSize = 0;
let totalMemoryUsage = 0;
const tierStats: PoolStats[] = [];
for (const pool of this.pools) {
const stats = pool.getStats();
tierStats.push(stats);
totalSize += stats.size;
totalMaxSize += stats.maxSize;
totalMemoryUsage += stats.estimatedMemoryUsage;
}
const hitRate = this.totalObtained > 0 ?
(this.totalObtained - this.getTotalCreated()) / this.totalObtained : 0;
return {
totalSize,
totalMaxSize,
totalMemoryUsage,
tierStats,
hitRate
};
}
/**
* 获取总创建数量
*/
private getTotalCreated(): number {
return this.pools.reduce((total, pool) => total + pool.getStats().totalCreated, 0);
}
}
/**
* 池管理器
* 统一管理所有对象池
*/
export class PoolManager {
private static instance: PoolManager;
private pools = new Map<string, Pool<any> | TieredObjectPool<any>>();
private autoCompactInterval = 60000; // 60秒
private lastCompactTime = 0;
public static getInstance(): PoolManager {
if (!PoolManager.instance) {
PoolManager.instance = new PoolManager();
}
return PoolManager.instance;
}
/**
* 注册池
* @param name 池名称
* @param pool 池实例
*/
public registerPool<T extends IPoolable>(name: string, pool: Pool<T> | TieredObjectPool<T>): void {
this.pools.set(name, pool);
}
/**
* 获取池
* @param name 池名称
* @returns 池实例
*/
public getPool<T extends IPoolable>(name: string): Pool<T> | TieredObjectPool<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;
}
}
/**
* 压缩所有池(清理碎片)
*/
public compactAllPools(): void {
// 对于标准池,可以考虑清理一些长时间未使用的对象
// 这里简单实现为重置统计信息
for (const pool of this.pools.values()) {
if (pool instanceof Pool) {
pool.resetStats();
}
}
}
/**
* 获取所有池的统计信息
*/
public getAllStats(): Map<string, any> {
const stats = new Map<string, any>();
for (const [name, pool] of this.pools.entries()) {
if (pool instanceof Pool) {
stats.set(name, pool.getStats());
} else if (pool instanceof TieredObjectPool) {
stats.set(name, pool.getStats());
}
}
return stats;
}
/**
* 生成性能报告
*/
public generateReport(): string {
const lines: string[] = [];
lines.push('=== Pool Manager Report ===');
let totalMemory = 0;
for (const [name, pool] of this.pools.entries()) {
lines.push(`\n${name}:`);
if (pool instanceof Pool) {
const stats = pool.getStats();
lines.push(` Type: Standard Pool`);
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`);
totalMemory += stats.estimatedMemoryUsage;
} else if (pool instanceof TieredObjectPool) {
const stats = pool.getStats();
lines.push(` Type: Tiered Pool`);
lines.push(` Total Size: ${stats.totalSize}/${stats.totalMaxSize}`);
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
lines.push(` Memory: ${(stats.totalMemoryUsage / 1024).toFixed(1)} KB`);
totalMemory += stats.totalMemoryUsage;
}
}
lines.push(`\nTotal Memory Usage: ${(totalMemory / 1024 / 1024).toFixed(2)} MB`);
return lines.join('\n');
}
}

View File

@@ -0,0 +1,29 @@
/**
* 可池化对象接口
*/
export interface IPoolable {
/**
* 重置对象状态,准备重用
*/
reset(): void;
}
/**
* 对象池统计信息
*/
export interface PoolStats {
/** 池中对象数量 */
size: number;
/** 池的最大大小 */
maxSize: number;
/** 总共创建的对象数量 */
totalCreated: number;
/** 总共获取的次数 */
totalObtained: number;
/** 总共释放的次数 */
totalReleased: number;
/** 命中率(从池中获取的比例) */
hitRate: number;
/** 内存使用估算(字节) */
estimatedMemoryUsage: number;
}

View File

@@ -0,0 +1,282 @@
import { IPoolable, PoolStats } from './IPoolable';
/**
* 高性能通用对象池
* 支持任意类型的对象池化,包含详细的统计信息
*/
export class Pool<T extends IPoolable> {
private static _pools = new Map<Function, Pool<any>>();
private _objects: T[] = [];
private _createFn: () => T;
private _maxSize: number;
private _stats: PoolStats;
private _objectSize: number; // 估算的单个对象大小
/**
* 构造函数
* @param createFn 创建对象的函数
* @param maxSize 池的最大大小默认100
* @param estimatedObjectSize 估算的单个对象大小字节默认1024
*/
constructor(createFn: () => T, maxSize: number = 100, estimatedObjectSize: number = 1024) {
this._createFn = createFn;
this._maxSize = maxSize;
this._objectSize = estimatedObjectSize;
this._stats = {
size: 0,
maxSize,
totalCreated: 0,
totalObtained: 0,
totalReleased: 0,
hitRate: 0,
estimatedMemoryUsage: 0
};
}
/**
* 获取指定类型的对象池
* @param type 对象类型
* @param maxSize 池的最大大小
* @param estimatedObjectSize 估算的单个对象大小
* @returns 对象池实例
*/
public static getPool<T extends IPoolable>(
type: new (...args: unknown[]) => T,
maxSize: number = 100,
estimatedObjectSize: number = 1024
): Pool<T> {
let pool = this._pools.get(type);
if (!pool) {
pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize);
this._pools.set(type, pool);
}
return pool;
}
/**
* 从池中获取对象
* @returns 对象实例
*/
public obtain(): T {
this._stats.totalObtained++;
if (this._objects.length > 0) {
const obj = this._objects.pop()!;
this._stats.size--;
this._updateHitRate();
this._updateMemoryUsage();
return obj;
}
// 池中没有可用对象,创建新对象
this._stats.totalCreated++;
this._updateHitRate();
return this._createFn();
}
/**
* 释放对象回池中
* @param obj 要释放的对象
*/
public release(obj: T): void {
if (!obj) return;
this._stats.totalReleased++;
// 如果池未满,将对象放回池中
if (this._stats.size < this._maxSize) {
// 重置对象状态
obj.reset();
this._objects.push(obj);
this._stats.size++;
this._updateMemoryUsage();
}
// 如果池已满,让对象被垃圾回收
}
/**
* 获取池统计信息
* @returns 统计信息对象
*/
public getStats(): Readonly<PoolStats> {
return { ...this._stats };
}
/**
* 清空池
*/
public clear(): void {
// 重置所有对象
for (const obj of this._objects) {
obj.reset();
}
this._objects.length = 0;
this._stats.size = 0;
this._updateMemoryUsage();
}
/**
* 压缩池(移除多余的对象)
* @param targetSize 目标大小,默认为当前大小的一半
*/
public compact(targetSize?: number): void {
const target = targetSize ?? Math.floor(this._objects.length / 2);
while (this._objects.length > target) {
const obj = this._objects.pop();
if (obj) {
obj.reset();
this._stats.size--;
}
}
this._updateMemoryUsage();
}
/**
* 预填充池
* @param count 预填充的对象数量
*/
public prewarm(count: number): void {
const actualCount = Math.min(count, this._maxSize - this._objects.length);
for (let i = 0; i < actualCount; i++) {
const obj = this._createFn();
obj.reset();
this._objects.push(obj);
this._stats.totalCreated++;
this._stats.size++;
}
this._updateMemoryUsage();
}
/**
* 设置最大池大小
* @param maxSize 新的最大大小
*/
public setMaxSize(maxSize: number): void {
this._maxSize = maxSize;
this._stats.maxSize = maxSize;
// 如果当前池大小超过新的最大值,进行压缩
if (this._objects.length > maxSize) {
this.compact(maxSize);
}
}
/**
* 获取池中可用对象数量
* @returns 可用对象数量
*/
public getAvailableCount(): number {
return this._objects.length;
}
/**
* 检查池是否为空
* @returns 如果池为空返回true
*/
public isEmpty(): boolean {
return this._objects.length === 0;
}
/**
* 检查池是否已满
* @returns 如果池已满返回true
*/
public isFull(): boolean {
return this._objects.length >= this._maxSize;
}
/**
* 获取所有已注册的池类型
* @returns 所有池类型的数组
*/
public static getAllPoolTypes(): Function[] {
return Array.from(this._pools.keys());
}
/**
* 获取所有池的统计信息
* @returns 包含所有池统计信息的对象
*/
public static getAllPoolStats(): Record<string, PoolStats> {
const stats: Record<string, PoolStats> = {};
for (const [type, pool] of this._pools) {
const typeName = type.name || type.toString();
stats[typeName] = pool.getStats();
}
return stats;
}
/**
* 压缩所有池
*/
public static compactAllPools(): void {
for (const pool of this._pools.values()) {
pool.compact();
}
}
/**
* 清空所有池
*/
public static clearAllPools(): void {
for (const pool of this._pools.values()) {
pool.clear();
}
this._pools.clear();
}
/**
* 获取全局池统计信息的格式化字符串
* @returns 格式化的统计信息字符串
*/
public static getGlobalStatsString(): string {
const stats = this.getAllPoolStats();
const lines: string[] = ['=== Object Pool Global Statistics ===', ''];
if (Object.keys(stats).length === 0) {
lines.push('No pools registered');
return lines.join('\n');
}
for (const [typeName, stat] of Object.entries(stats)) {
lines.push(`${typeName}:`);
lines.push(` Size: ${stat.size}/${stat.maxSize}`);
lines.push(` Hit Rate: ${(stat.hitRate * 100).toFixed(1)}%`);
lines.push(` Total Created: ${stat.totalCreated}`);
lines.push(` Total Obtained: ${stat.totalObtained}`);
lines.push(` Memory: ${(stat.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
lines.push('');
}
return lines.join('\n');
}
/**
* 更新命中率
*/
private _updateHitRate(): void {
if (this._stats.totalObtained === 0) {
this._stats.hitRate = 0;
} else {
const hits = this._stats.totalObtained - this._stats.totalCreated;
this._stats.hitRate = hits / this._stats.totalObtained;
}
}
/**
* 更新内存使用估算
*/
private _updateMemoryUsage(): void {
this._stats.estimatedMemoryUsage = this._stats.size * this._objectSize;
}
}

View File

@@ -0,0 +1,231 @@
import { IPoolable, PoolStats } from './IPoolable';
import { Pool } from './Pool';
/**
* 池管理器
* 统一管理所有对象池
*/
export class PoolManager {
private static instance: PoolManager;
private pools = new Map<string, Pool<any>>();
private autoCompactInterval = 60000; // 60秒
private lastCompactTime = 0;
public static getInstance(): PoolManager {
if (!PoolManager.instance) {
PoolManager.instance = new PoolManager();
}
return PoolManager.instance;
}
/**
* 注册池
* @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;
}
}

View File

@@ -0,0 +1,3 @@
export * from './IPoolable';
export * from './Pool';
export * from './PoolManager';

View File

@@ -4,4 +4,5 @@ export * from './Emitter';
export * from './GlobalManager';
export * from './PerformanceMonitor';
export { Time } from './Time';
export * from './Debug';
export * from './Debug';
export * from './Logger';