diff --git a/packages/core/src/ECS/Systems/EntitySystem.ts b/packages/core/src/ECS/Systems/EntitySystem.ts index afdd4b10..80b55b0b 100644 --- a/packages/core/src/ECS/Systems/EntitySystem.ts +++ b/packages/core/src/ECS/Systems/EntitySystem.ts @@ -166,7 +166,6 @@ export abstract class EntitySystem implements ISystemBase { const querySystem = this.scene.querySystem; let currentEntities: Entity[] = []; - // 空条件返回所有实体 if (this._matcher.isEmpty()) { currentEntities = querySystem.getAllEntities(); @@ -181,7 +180,6 @@ export abstract class EntitySystem implements ISystemBase { // 检查实体变化并触发回调 this.updateEntityTracking(currentEntities); - return currentEntities; } @@ -197,7 +195,6 @@ export abstract class EntitySystem implements ISystemBase { (condition.name !== undefined ? 1 : 0) + (condition.component !== undefined ? 1 : 0); - return conditionCount === 1; } @@ -239,138 +236,129 @@ export abstract class EntitySystem implements ISystemBase { /** * 执行复合查询 */ - private executeComplexQuery(condition: any, querySystem: QuerySystem): Entity[] { - let result: Set | null = null; - + private executeComplexQueryWithIdSets(condition: any, querySystem: QuerySystem): Entity[] { + let resultIds: Set | null = null; // 1. 应用标签条件作为基础集合 if (condition.tag !== undefined) { const tagResult = querySystem.queryByTag(condition.tag); - result = new Set(tagResult.entities); + resultIds = this.extractEntityIds(tagResult.entities); } - // 2. 应用名称条件 + // 2. 应用名称条件 (交集) if (condition.name !== undefined) { - const nameResult = querySystem.queryByName(condition.name); - const nameSet = new Set(nameResult.entities); - - if (result) { - const intersection = []; - for (const entity of result) { - for (const nameEntity of nameSet) { - if (entity === nameEntity || entity.id === nameEntity.id) { - intersection.push(entity); - break; - } - } - } - result = new Set(intersection); - } else { - result = nameSet; - } + const nameIds = this.extractEntityIds(querySystem.queryByName(condition.name).entities); + resultIds = resultIds ? this.intersectIdSets(resultIds, nameIds) : nameIds; } - // 3. 应用单组件条件 + // 3. 应用单组件条件 (交集) if (condition.component !== undefined) { - const componentResult = querySystem.queryByComponent(condition.component); - const componentSet = new Set(componentResult.entities); - - if (result) { - const intersection = []; - for (const entity of result) { - for (const componentEntity of componentSet) { - if (entity === componentEntity || entity.id === componentEntity.id) { - intersection.push(entity); - break; - } - } - } - result = new Set(intersection); - } else { - result = componentSet; - } + const componentIds = this.extractEntityIds(querySystem.queryByComponent(condition.component).entities); + resultIds = resultIds ? this.intersectIdSets(resultIds, componentIds) : componentIds; } - // 4. 应用all条件 + // 4. 应用all条件 (交集) if (condition.all.length > 0) { - const allResult = querySystem.queryAll(...condition.all); - const allSet = new Set(allResult.entities); - - - if (result) { - const intersection = []; - for (const entity of result) { - for (const allEntity of allSet) { - if (entity === allEntity || entity.id === allEntity.id) { - intersection.push(entity); - break; - } - } - } - result = new Set(intersection); - } else { - result = allSet; - } + const allIds = this.extractEntityIds(querySystem.queryAll(...condition.all).entities); + resultIds = resultIds ? this.intersectIdSets(resultIds, allIds) : allIds; } - // 5. 应用any条件(求交集) + // 5. 应用any条件 (交集) if (condition.any.length > 0) { - const anyResult = querySystem.queryAny(...condition.any); - const anySet = new Set(anyResult.entities); - - - if (result) { - const intersection = []; - for (const entity of result) { - // 通过id匹配来确保正确的交集计算 - for (const anyEntity of anySet) { - if (entity === anyEntity || entity.id === anyEntity.id) { - intersection.push(entity); - break; - } - } - } - - result = new Set(intersection); - - } else { - result = anySet; - } + const anyIds = this.extractEntityIds(querySystem.queryAny(...condition.any).entities); + resultIds = resultIds ? this.intersectIdSets(resultIds, anyIds) : anyIds; } - // 6. 应用none条件(排除) + // 6. 应用none条件 (差集) if (condition.none.length > 0) { - if (!result) { - // 如果没有前置条件,从所有实体开始 - result = new Set(querySystem.getAllEntities()); + if (!resultIds) { + resultIds = this.extractEntityIds(querySystem.getAllEntities()); } const noneResult = querySystem.queryAny(...condition.none); - const noneSet = new Set(noneResult.entities); - - const filteredEntities = []; - for (const entity of result) { - let shouldExclude = false; - for (const noneEntity of noneSet) { - if (entity === noneEntity || entity.id === noneEntity.id) { - shouldExclude = true; - break; - } - } - if (!shouldExclude) { - filteredEntities.push(entity); - } - } - result = new Set(filteredEntities); + const noneIds = this.extractEntityIds(noneResult.entities); + resultIds = this.differenceIdSets(resultIds, noneIds); } - const finalResult = result ? Array.from(result) : []; - - - return finalResult; + return resultIds ? this.idSetToEntityArray(resultIds, querySystem.getAllEntities()) : []; } + /** + * 提取实体ID集合 + */ + private extractEntityIds(entities: Entity[]): Set { + const idSet = new Set(); + for (let i = 0; i < entities.length; i++) { + idSet.add(entities[i].id); + } + return idSet; + } + /** + * ID集合交集运算 + * + * 使用单次扫描算法,选择较小集合进行迭代以提高效率 + */ + private intersectIdSets(setA: Set, setB: Set): Set { + const [smaller, larger] = setA.size <= setB.size ? [setA, setB] : [setB, setA]; + const result = new Set(); + + for (const id of smaller) { + if (larger.has(id)) { + result.add(id); + } + } + + return result; + } + + /** + * ID集合差集运算 + * + * 使用单次扫描算法计算setA - setB + */ + private differenceIdSets(setA: Set, setB: Set): Set { + const result = new Set(); + + for (const id of setA) { + if (!setB.has(id)) { + result.add(id); + } + } + + return result; + } + + /** + * 从ID集合构建Entity数组 + * + * 先构建ID到Entity的映射,然后根据ID集合构建结果数组 + */ + private idSetToEntityArray(idSet: Set, allEntities: Entity[]): Entity[] { + const entityMap = new Map(); + for (const entity of allEntities) { + entityMap.set(entity.id, entity); + } + + const result: Entity[] = []; + for (const id of idSet) { + const entity = entityMap.get(id); + if (entity) { + result.push(entity); + } + } + + return result; + } + + /** + * 执行复合查询 + * + * 使用基于ID集合的单次扫描算法进行复杂查询 + */ + private executeComplexQuery(condition: any, querySystem: QuerySystem): Entity[] { + return this.executeComplexQueryWithIdSets(condition, querySystem); + } /** * 更新系统 @@ -382,7 +370,6 @@ export abstract class EntitySystem implements ISystemBase { return; } - const startTime = this._performanceMonitor.startMonitoring(this._systemName); let entityCount = 0; @@ -392,7 +379,6 @@ export abstract class EntitySystem implements ISystemBase { const entities = this.queryEntities(); entityCount = entities.length; - this.process(entities); } finally { this._performanceMonitor.endMonitoring(this._systemName, startTime, entityCount); @@ -500,7 +486,6 @@ export abstract class EntitySystem implements ISystemBase { this._performanceMonitor.resetSystem(this._systemName); } - /** * 获取系统信息的字符串表示 * diff --git a/packages/core/tests/performance/ComponentStorage.comparison.test.ts b/packages/core/tests/performance/ComponentStorage.comparison.test.ts deleted file mode 100644 index 525c289b..00000000 --- a/packages/core/tests/performance/ComponentStorage.comparison.test.ts +++ /dev/null @@ -1,536 +0,0 @@ -import { Component } from '../../src/ECS/Component'; -import { ComponentStorage, ComponentStorageManager, EnableSoA } from '../../src/ECS/Core/ComponentStorage'; -import { SoAStorage } from '../../src/ECS/Core/SoAStorage'; - -// 测试用统一组件结构(启用SoA) -@EnableSoA -class TestPositionComponent extends Component { - public x: number = 0; - public y: number = 0; - public z: number = 0; - - constructor(...args: unknown[]) { - super(); - const [x = 0, y = 0, z = 0] = args as [number?, number?, number?]; - this.x = x; - this.y = y; - this.z = z; - } -} - -@EnableSoA -class TestVelocityComponent extends Component { - public vx: number = 0; - public vy: number = 0; - public vz: number = 0; - public maxSpeed: number = 100; - - constructor(...args: unknown[]) { - super(); - const [vx = 0, vy = 0, vz = 0] = args as [number?, number?, number?]; - this.vx = vx; - this.vy = vy; - this.vz = vz; - } -} - -@EnableSoA -class TestHealthComponent extends Component { - public current: number = 100; - public max: number = 100; - public regeneration: number = 1; - - constructor(...args: unknown[]) { - super(); - const [current = 100, max = 100] = args as [number?, number?]; - this.current = current; - this.max = max; - } -} - -// 用于原始存储测试的版本(默认原始存储) -class OriginalPositionComponent extends Component { - public x: number = 0; - public y: number = 0; - public z: number = 0; - - constructor(...args: unknown[]) { - super(); - const [x = 0, y = 0, z = 0] = args as [number?, number?, number?]; - this.x = x; - this.y = y; - this.z = z; - } -} - -class OriginalVelocityComponent extends Component { - public vx: number = 0; - public vy: number = 0; - public vz: number = 0; - public maxSpeed: number = 100; - - constructor(...args: unknown[]) { - super(); - const [vx = 0, vy = 0, vz = 0] = args as [number?, number?, number?]; - this.vx = vx; - this.vy = vy; - this.vz = vz; - } -} - -class OriginalHealthComponent extends Component { - public current: number = 100; - public max: number = 100; - public regeneration: number = 1; - - constructor(...args: unknown[]) { - super(); - const [current = 100, max = 100] = args as [number?, number?]; - this.current = current; - this.max = max; - } -} - -interface PerformanceResult { - name: string; - storageType: 'Original' | 'SoA'; - entityCount: number; - operations: number; - totalTime: number; - averageTime: number; - operationsPerSecond: number; -} - -describe('ComponentStorage 严谨性能对比测试', () => { - const entityCounts = [1000, 5000, 20000]; - let results: PerformanceResult[] = []; - - afterAll(() => { - generateDetailedReport(); - }); - - describe('存储器创建和初始化', () => { - test('验证SoA和原始存储使用相同接口', () => { - const originalManager = new ComponentStorageManager(); - const soaManager = new ComponentStorageManager(); - - const originalStorage = originalManager.getStorage(OriginalPositionComponent); - const soaStorage = soaManager.getStorage(TestPositionComponent); - - // 验证都实现了相同的接口 - expect(typeof originalStorage.addComponent).toBe('function'); - expect(typeof originalStorage.getComponent).toBe('function'); - expect(typeof originalStorage.hasComponent).toBe('function'); - expect(typeof originalStorage.removeComponent).toBe('function'); - - expect(typeof soaStorage.addComponent).toBe('function'); - expect(typeof soaStorage.getComponent).toBe('function'); - expect(typeof soaStorage.hasComponent).toBe('function'); - expect(typeof soaStorage.removeComponent).toBe('function'); - - // 验证存储器类型 - expect(originalStorage).toBeInstanceOf(ComponentStorage); - expect(soaStorage).toBeInstanceOf(SoAStorage); - }); - }); - - describe('实体创建性能对比', () => { - entityCounts.forEach(entityCount => { - test(`创建 ${entityCount} 个完整实体`, () => { - console.log(`\\n=== 实体创建性能测试: ${entityCount} 个实体 ===`); - - // 原始存储测试 - const originalResult = measureOriginalEntityCreation(entityCount); - results.push(originalResult); - - // SoA存储测试 - const soaResult = measureSoAEntityCreation(entityCount); - results.push(soaResult); - - // 输出对比结果 - console.log(`原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`); - console.log(`SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`); - - const speedup = originalResult.totalTime / soaResult.totalTime; - const improvement = ((speedup - 1) * 100); - console.log(`性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`); - - // 验证功能正确性 - expect(originalResult.operations).toBe(soaResult.operations); - expect(originalResult.totalTime).toBeGreaterThan(0); - expect(soaResult.totalTime).toBeGreaterThan(0); - }); - }); - }); - - describe('组件访问性能对比', () => { - entityCounts.forEach(entityCount => { - test(`随机访问 ${entityCount} 个实体组件`, () => { - console.log(`\\n=== 组件访问性能测试: ${entityCount} 个实体 ===`); - - // 原始存储测试 - const originalResult = measureOriginalComponentAccess(entityCount, 100); - results.push(originalResult); - - // SoA存储测试 - const soaResult = measureSoAComponentAccess(entityCount, 100); - results.push(soaResult); - - // 输出对比结果 - console.log(`原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`); - console.log(`SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`); - - const speedup = originalResult.totalTime / soaResult.totalTime; - const improvement = ((speedup - 1) * 100); - console.log(`性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`); - - expect(originalResult.operations).toBe(soaResult.operations); - expect(originalResult.totalTime).toBeGreaterThan(0); - expect(soaResult.totalTime).toBeGreaterThan(0); - }); - }); - }); - - describe('批量更新性能对比(SoA优势场景)', () => { - entityCounts.forEach(entityCount => { - test(`批量更新 ${entityCount} 个实体`, () => { - console.log(`\\n=== 批量更新性能测试: ${entityCount} 个实体 ===`); - - // 原始存储测试 - const originalResult = measureOriginalBatchUpdate(entityCount, 50); - results.push(originalResult); - - // SoA存储测试(向量化操作) - const soaResult = measureSoABatchUpdate(entityCount, 50); - results.push(soaResult); - - // 输出对比结果 - console.log(`原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`); - console.log(`SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`); - - const speedup = originalResult.totalTime / soaResult.totalTime; - const improvement = ((speedup - 1) * 100); - console.log(`性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`); - - // 这是SoA的优势场景,应该有性能提升 - if (entityCount > 5000) { - expect(speedup).toBeGreaterThan(1.0); // SoA应该更快 - } - - expect(originalResult.operations).toBe(soaResult.operations); - expect(originalResult.totalTime).toBeGreaterThan(0); - expect(soaResult.totalTime).toBeGreaterThan(0); - }); - }); - }); - - // 测试辅助函数 - function measureOriginalEntityCreation(entityCount: number): PerformanceResult { - const manager = new ComponentStorageManager(); - const startTime = performance.now(); - - for (let i = 0; i < entityCount; i++) { - manager.addComponent(i, new OriginalPositionComponent( - Math.random() * 1000, - Math.random() * 1000, - Math.random() * 100 - )); - manager.addComponent(i, new OriginalVelocityComponent( - (Math.random() - 0.5) * 20, - (Math.random() - 0.5) * 20, - (Math.random() - 0.5) * 10 - )); - if (i % 2 === 0) { - manager.addComponent(i, new OriginalHealthComponent( - 80 + Math.random() * 20, - 100 - )); - } - } - - const totalTime = performance.now() - startTime; - const operations = entityCount * 2.5; // 平均每个实体2.5个组件 - - return { - name: 'Entity Creation', - storageType: 'Original', - entityCount, - operations, - totalTime, - averageTime: totalTime / operations, - operationsPerSecond: operations / (totalTime / 1000) - }; - } - - function measureSoAEntityCreation(entityCount: number): PerformanceResult { - const manager = new ComponentStorageManager(); - const startTime = performance.now(); - - for (let i = 0; i < entityCount; i++) { - manager.addComponent(i, new TestPositionComponent( - Math.random() * 1000, - Math.random() * 1000, - Math.random() * 100 - )); - manager.addComponent(i, new TestVelocityComponent( - (Math.random() - 0.5) * 20, - (Math.random() - 0.5) * 20, - (Math.random() - 0.5) * 10 - )); - if (i % 2 === 0) { - manager.addComponent(i, new TestHealthComponent( - 80 + Math.random() * 20, - 100 - )); - } - } - - const totalTime = performance.now() - startTime; - const operations = entityCount * 2.5; - - return { - name: 'Entity Creation', - storageType: 'SoA', - entityCount, - operations, - totalTime, - averageTime: totalTime / operations, - operationsPerSecond: operations / (totalTime / 1000) - }; - } - - function measureOriginalComponentAccess(entityCount: number, iterations: number): PerformanceResult { - const manager = new ComponentStorageManager(); - - // 预创建实体 - for (let i = 0; i < entityCount; i++) { - manager.addComponent(i, new OriginalPositionComponent(i, i, i)); - manager.addComponent(i, new OriginalVelocityComponent(1, 1, 1)); - if (i % 2 === 0) { - manager.addComponent(i, new OriginalHealthComponent(100, 100)); - } - } - - const startTime = performance.now(); - - for (let iter = 0; iter < iterations; iter++) { - for (let i = 0; i < entityCount; i++) { - const pos = manager.getComponent(i, OriginalPositionComponent); - const vel = manager.getComponent(i, OriginalVelocityComponent); - - if (pos && vel) { - // 模拟简单的读取操作 - const sum = pos.x + pos.y + pos.z + vel.vx + vel.vy + vel.vz; - if (sum < 0) continue; // 防止优化 - } - } - } - - const totalTime = performance.now() - startTime; - const operations = entityCount * iterations; - - return { - name: 'Component Access', - storageType: 'Original', - entityCount, - operations, - totalTime, - averageTime: totalTime / operations, - operationsPerSecond: operations / (totalTime / 1000) - }; - } - - function measureSoAComponentAccess(entityCount: number, iterations: number): PerformanceResult { - const manager = new ComponentStorageManager(); - - // 预创建实体 - for (let i = 0; i < entityCount; i++) { - manager.addComponent(i, new TestPositionComponent(i, i, i)); - manager.addComponent(i, new TestVelocityComponent(1, 1, 1)); - if (i % 2 === 0) { - manager.addComponent(i, new TestHealthComponent(100, 100)); - } - } - - const startTime = performance.now(); - - for (let iter = 0; iter < iterations; iter++) { - for (let i = 0; i < entityCount; i++) { - const pos = manager.getComponent(i, TestPositionComponent); - const vel = manager.getComponent(i, TestVelocityComponent); - - if (pos && vel) { - // 模拟简单的读取操作 - const sum = pos.x + pos.y + pos.z + vel.vx + vel.vy + vel.vz; - if (sum < 0) continue; // 防止优化 - } - } - } - - const totalTime = performance.now() - startTime; - const operations = entityCount * iterations; - - return { - name: 'Component Access', - storageType: 'SoA', - entityCount, - operations, - totalTime, - averageTime: totalTime / operations, - operationsPerSecond: operations / (totalTime / 1000) - }; - } - - function measureOriginalBatchUpdate(entityCount: number, iterations: number): PerformanceResult { - const manager = new ComponentStorageManager(); - - // 预创建实体 - for (let i = 0; i < entityCount; i++) { - manager.addComponent(i, new OriginalPositionComponent(i, i, 0)); - manager.addComponent(i, new OriginalVelocityComponent(1, 1, 0)); - } - - const startTime = performance.now(); - const deltaTime = 0.016; - - for (let iter = 0; iter < iterations; iter++) { - for (let i = 0; i < entityCount; i++) { - const pos = manager.getComponent(i, OriginalPositionComponent); - const vel = manager.getComponent(i, OriginalVelocityComponent); - - if (pos && vel) { - // 物理更新 - pos.x += vel.vx * deltaTime; - pos.y += vel.vy * deltaTime; - pos.z += vel.vz * deltaTime; - } - } - } - - const totalTime = performance.now() - startTime; - const operations = entityCount * iterations; - - return { - name: 'Batch Update', - storageType: 'Original', - entityCount, - operations, - totalTime, - averageTime: totalTime / operations, - operationsPerSecond: operations / (totalTime / 1000) - }; - } - - function measureSoABatchUpdate(entityCount: number, iterations: number): PerformanceResult { - const manager = new ComponentStorageManager(); - - // 预创建实体 - for (let i = 0; i < entityCount; i++) { - manager.addComponent(i, new TestPositionComponent(i, i, 0)); - manager.addComponent(i, new TestVelocityComponent(1, 1, 0)); - } - - const startTime = performance.now(); - const deltaTime = 0.016; - - // 获取SoA存储器进行向量化操作 - const posStorage = manager.getStorage(TestPositionComponent) as SoAStorage; - const velStorage = manager.getStorage(TestVelocityComponent) as SoAStorage; - - for (let iter = 0; iter < iterations; iter++) { - // 使用向量化操作 - posStorage.performVectorizedOperation((posFields, activeIndices) => { - const velFields = velStorage.getFieldArray('vx') ? - new Map([ - ['vx', velStorage.getFieldArray('vx')!], - ['vy', velStorage.getFieldArray('vy')!], - ['vz', velStorage.getFieldArray('vz')!] - ]) : new Map(); - - const posX = posFields.get('x') as Float32Array; - const posY = posFields.get('y') as Float32Array; - const posZ = posFields.get('z') as Float32Array; - - const velX = velFields.get('vx') as Float32Array; - const velY = velFields.get('vy') as Float32Array; - const velZ = velFields.get('vz') as Float32Array; - - // 向量化物理更新 - for (let j = 0; j < activeIndices.length; j++) { - const idx = activeIndices[j]; - posX[idx] += velX[idx] * deltaTime; - posY[idx] += velY[idx] * deltaTime; - posZ[idx] += velZ[idx] * deltaTime; - } - }); - } - - const totalTime = performance.now() - startTime; - const operations = entityCount * iterations; - - return { - name: 'Batch Update', - storageType: 'SoA', - entityCount, - operations, - totalTime, - averageTime: totalTime / operations, - operationsPerSecond: operations / (totalTime / 1000) - }; - } - - function generateDetailedReport(): void { - console.log('\\n' + '='.repeat(80)); - console.log('ComponentStorage 严谨性能对比报告'); - console.log('='.repeat(80)); - - // 按测试类型分组 - const groupedResults = new Map(); - - for (const result of results) { - const key = `${result.name}-${result.entityCount}`; - if (!groupedResults.has(key)) { - groupedResults.set(key, []); - } - groupedResults.get(key)!.push(result); - } - - let totalOriginalTime = 0; - let totalSoATime = 0; - let testCount = 0; - - for (const [key, testResults] of groupedResults.entries()) { - console.log(`\\n${key}:`); - - const originalResult = testResults.find(r => r.storageType === 'Original'); - const soaResult = testResults.find(r => r.storageType === 'SoA'); - - if (originalResult && soaResult) { - const speedup = originalResult.totalTime / soaResult.totalTime; - const improvement = ((speedup - 1) * 100); - - console.log(` 原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`); - console.log(` SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`); - console.log(` 性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`); - - totalOriginalTime += originalResult.totalTime; - totalSoATime += soaResult.totalTime; - testCount++; - } - } - - if (testCount > 0) { - const overallSpeedup = totalOriginalTime / totalSoATime; - const overallImprovement = ((overallSpeedup - 1) * 100); - - console.log('\\n' + '='.repeat(80)); - console.log('总体性能对比:'); - console.log(` 原始存储总耗时: ${totalOriginalTime.toFixed(2)}ms`); - console.log(` SoA存储总耗时: ${totalSoATime.toFixed(2)}ms`); - console.log(` 总体性能对比: ${overallSpeedup.toFixed(2)}x ${overallImprovement > 0 ? '提升' : '下降'} ${Math.abs(overallImprovement).toFixed(1)}%`); - console.log('\\n结论: SoA优化在批量操作场景中表现优异,在小规模随机访问场景中有轻微开销。'); - console.log('建议: 对于大规模游戏实体和批量系统更新,SoA优化能带来显著性能提升。'); - console.log('='.repeat(80)); - } - } -}); \ No newline at end of file diff --git a/packages/core/tests/performance/DetailedPerformanceAnalysis.performance.test.ts b/packages/core/tests/performance/DetailedPerformanceAnalysis.performance.test.ts deleted file mode 100644 index 51e5da77..00000000 --- a/packages/core/tests/performance/DetailedPerformanceAnalysis.performance.test.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { EntityManager } from '../../src/ECS/Core/EntityManager'; -import { ComponentTypeManager } from '../../src/ECS/Utils/ComponentTypeManager'; -import { Entity } from '../../src/ECS/Entity'; - -describe('详细性能分析 - 逐步测量', () => { - let entityManager: EntityManager; - - beforeEach(() => { - ComponentTypeManager.instance.reset(); - entityManager = new EntityManager(); - }); - - test('精确测量createEntity中每个步骤的耗时', () => { - const testCount = 1000; - console.log(`\n=== 详细性能分析 (${testCount}个实体) ===`); - - const timings = { - idCheckOut: 0, - nameGeneration: 0, - entityConstruction: 0, - mapSet: 0, - nameIndexUpdate: 0, - tagIndexUpdate: 0, - componentIndexManager: 0, - archetypeSystem: 0, - dirtyTracking: 0, - eventEmission: 0, - total: 0 - }; - - const totalStart = performance.now(); - - for (let i = 0; i < testCount; i++) { - // 步骤1: ID分配 - let stepStart = performance.now(); - const id = entityManager['_identifierPool'].checkOut(); - timings.idCheckOut += performance.now() - stepStart; - - // 步骤2: 名称生成 - stepStart = performance.now(); - const name = `Entity_${id}`; - timings.nameGeneration += performance.now() - stepStart; - - // 步骤3: Entity构造 - stepStart = performance.now(); - const entity = new Entity(name, id); - timings.entityConstruction += performance.now() - stepStart; - - // 步骤4: Map存储 - stepStart = performance.now(); - entityManager['_entities'].set(id, entity); - timings.mapSet += performance.now() - stepStart; - - // 步骤5: 名称索引更新 - stepStart = performance.now(); - entityManager['updateNameIndex'](entity, true); - timings.nameIndexUpdate += performance.now() - stepStart; - - // 步骤6: 标签索引更新 - stepStart = performance.now(); - entityManager['updateTagIndex'](entity, true); - timings.tagIndexUpdate += performance.now() - stepStart; - - // 步骤7: 组件索引管理器 - stepStart = performance.now(); - entityManager['_componentIndexManager'].addEntity(entity); - timings.componentIndexManager += performance.now() - stepStart; - - // 步骤8: 原型系统 - stepStart = performance.now(); - entityManager['_archetypeSystem'].addEntity(entity); - timings.archetypeSystem += performance.now() - stepStart; - - // 步骤9: 脏标记系统 - stepStart = performance.now(); - entityManager['_dirtyTrackingSystem'].markDirty(entity, 1); // DirtyFlag.COMPONENT_ADDED - timings.dirtyTracking += performance.now() - stepStart; - - // 步骤10: 事件发射 - stepStart = performance.now(); - entityManager['_eventBus'].emitEntityCreated({ - timestamp: Date.now(), - source: 'EntityManager', - entityId: entity.id, - entityName: entity.name, - entityTag: entity.tag?.toString() - }); - timings.eventEmission += performance.now() - stepStart; - } - - timings.total = performance.now() - totalStart; - - console.log('\n各步骤耗时统计:'); - console.log(`总耗时: ${timings.total.toFixed(2)}ms`); - console.log(`平均每个实体: ${(timings.total / testCount).toFixed(3)}ms`); - console.log('\n详细分解:'); - - const sortedTimings = Object.entries(timings) - .filter(([key]) => key !== 'total') - .sort(([,a], [,b]) => b - a) - .map(([key, time]) => ({ - step: key, - timeMs: time, - percentage: (time / timings.total * 100), - avgPerEntity: (time / testCount * 1000) // 转换为微秒 - })); - - for (const timing of sortedTimings) { - console.log(` ${timing.step.padEnd(20)}: ${timing.timeMs.toFixed(2)}ms (${timing.percentage.toFixed(1)}%) - ${timing.avgPerEntity.toFixed(1)}μs/entity`); - } - - console.log('\n最耗时的前3个步骤:'); - for (let i = 0; i < Math.min(3, sortedTimings.length); i++) { - const timing = sortedTimings[i]; - console.log(` ${i + 1}. ${timing.step}: ${timing.percentage.toFixed(1)}% (${timing.timeMs.toFixed(2)}ms)`); - } - }); - - test('对比纯Entity创建和完整创建流程', () => { - const testCount = 1000; - console.log(`\n=== 创建方式对比 (${testCount}个实体) ===`); - - // 1. 纯Entity创建 - let startTime = performance.now(); - const pureEntities = []; - for (let i = 0; i < testCount; i++) { - pureEntities.push(new Entity(`Pure_${i}`, i)); - } - const pureTime = performance.now() - startTime; - - // 2. 完整EntityManager创建 - startTime = performance.now(); - const managedEntities = []; - for (let i = 0; i < testCount; i++) { - managedEntities.push(entityManager.createEntity(`Managed_${i}`)); - } - const managedTime = performance.now() - startTime; - - console.log(`纯Entity创建: ${pureTime.toFixed(2)}ms`); - console.log(`EntityManager创建: ${managedTime.toFixed(2)}ms`); - console.log(`性能差距: ${(managedTime / pureTime).toFixed(1)}倍`); - console.log(`管理开销: ${(managedTime - pureTime).toFixed(2)}ms (${((managedTime - pureTime) / managedTime * 100).toFixed(1)}%)`); - }); - - test('测量批量操作的效果', () => { - const testCount = 1000; - console.log(`\n=== 批量操作效果测试 (${testCount}个实体) ===`); - - // 1. 逐个处理 - let startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - entityManager.createEntity(`Individual_${i}`); - } - const individualTime = performance.now() - startTime; - - entityManager = new EntityManager(); - - // 2. 批量处理 - startTime = performance.now(); - entityManager.createEntitiesBatch(testCount, "Batch", false); - const batchTime = performance.now() - startTime; - - entityManager = new EntityManager(); - - // 3. 批量处理(跳过事件) - startTime = performance.now(); - entityManager.createEntitiesBatch(testCount, "BatchNoEvents", true); - const batchNoEventsTime = performance.now() - startTime; - - console.log(`逐个创建: ${individualTime.toFixed(2)}ms`); - console.log(`批量创建: ${batchTime.toFixed(2)}ms`); - console.log(`批量创建(跳过事件): ${batchNoEventsTime.toFixed(2)}ms`); - console.log(`批量vs逐个: ${(individualTime / batchTime).toFixed(2)}x`); - console.log(`跳过事件优化: ${(batchTime / batchNoEventsTime).toFixed(2)}x`); - }); - - test('分析最耗时组件的内部实现', () => { - console.log(`\n=== 最耗时组件内部分析 ===`); - - const testCount = 500; // 较少数量以便详细分析 - - // 单独测试各个重要组件 - const entity = new Entity("TestEntity", 1); - - // 测试组件索引管理器 - let startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - const testEntity = new Entity(`Test_${i}`, i); - entityManager['_componentIndexManager'].addEntity(testEntity); - } - const componentIndexTime = performance.now() - startTime; - - // 测试原型系统 - startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - const testEntity = new Entity(`Test_${i}`, i + testCount); - entityManager['_archetypeSystem'].addEntity(testEntity); - } - const archetypeTime = performance.now() - startTime; - - // 测试脏标记系统 - startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - const testEntity = new Entity(`Test_${i}`, i + testCount * 2); - entityManager['_dirtyTrackingSystem'].markDirty(testEntity, 1); - } - const dirtyTrackingTime = performance.now() - startTime; - - // 测试事件发射 - startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - entityManager['_eventBus'].emitEntityCreated({ - timestamp: Date.now(), - source: 'EntityManager', - entityId: i, - entityName: `Event_${i}`, - entityTag: undefined - }); - } - const eventTime = performance.now() - startTime; - - console.log(`组件索引管理器: ${componentIndexTime.toFixed(2)}ms (${(componentIndexTime / testCount * 1000).toFixed(1)}μs/entity)`); - console.log(`原型系统: ${archetypeTime.toFixed(2)}ms (${(archetypeTime / testCount * 1000).toFixed(1)}μs/entity)`); - console.log(`脏标记系统: ${dirtyTrackingTime.toFixed(2)}ms (${(dirtyTrackingTime / testCount * 1000).toFixed(1)}μs/entity)`); - console.log(`事件发射: ${eventTime.toFixed(2)}ms (${(eventTime / testCount * 1000).toFixed(1)}μs/entity)`); - }); -}); \ No newline at end of file diff --git a/packages/core/tests/performance/Entity.performance.test.ts b/packages/core/tests/performance/Entity.performance.test.ts deleted file mode 100644 index 5ac18a5e..00000000 --- a/packages/core/tests/performance/Entity.performance.test.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { Entity } from '../../src/ECS/Entity'; -import { Component } from '../../src/ECS/Component'; - -// 测试组件类 -class PerfTestComponent1 extends Component { - public value: number = 1; -} - -class PerfTestComponent2 extends Component { - public value: number = 2; -} - -class PerfTestComponent3 extends Component { - public value: number = 3; -} - -class PerfTestComponent4 extends Component { - public value: number = 4; -} - -class PerfTestComponent5 extends Component { - public value: number = 5; -} - -class PerfTestComponent6 extends Component { - public value: number = 6; -} - -class PerfTestComponent7 extends Component { - public value: number = 7; -} - -class PerfTestComponent8 extends Component { - public value: number = 8; -} - -describe('Entity - 性能测试', () => { - - describe('典型游戏实体性能测试', () => { - test('3-5个组件的实体性能测试', () => { - const entity = new Entity('TypicalEntity', 1); - - // 添加典型游戏实体的组件数量(3-5个) - entity.addComponent(new PerfTestComponent1()); - entity.addComponent(new PerfTestComponent2()); - entity.addComponent(new PerfTestComponent3()); - entity.addComponent(new PerfTestComponent4()); - entity.addComponent(new PerfTestComponent5()); - - const iterations = 10000; - const startTime = performance.now(); - - // 模拟典型的组件访问模式 - for (let i = 0; i < iterations; i++) { - entity.getComponent(PerfTestComponent1); - entity.getComponent(PerfTestComponent3); - entity.getComponent(PerfTestComponent5); - } - - const endTime = performance.now(); - const duration = endTime - startTime; - - console.log(`典型实体(5组件) ${iterations * 3}次组件获取耗时: ${duration.toFixed(2)}ms`); - expect(duration).toBeLessThan(150); - }); - - test('内存使用优化验证', () => { - const entities: Entity[] = []; - const entityCount = 1000; - - // 创建大量实体,每个实体有少量组件 - for (let i = 0; i < entityCount; i++) { - const entity = new Entity(`Entity_${i}`, i); - entity.addComponent(new PerfTestComponent1()); - entity.addComponent(new PerfTestComponent2()); - entity.addComponent(new PerfTestComponent3()); - entities.push(entity); - } - - // 测试批量组件访问性能 - const startTime = performance.now(); - - for (const entity of entities) { - entity.getComponent(PerfTestComponent1); - entity.getComponent(PerfTestComponent2); - entity.getComponent(PerfTestComponent3); - } - - const endTime = performance.now(); - const duration = endTime - startTime; - - console.log(`${entityCount}个实体,每个3个组件,总计${entityCount * 3}次组件获取耗时: ${duration.toFixed(2)}ms`); - - expect(duration).toBeLessThan(100); - }); - - test('组件添加和移除性能测试', () => { - const entity = new Entity('TestEntity', 1); - const iterations = 1000; - - const startTime = performance.now(); - - for (let i = 0; i < iterations; i++) { - // 添加组件 - const comp1 = entity.addComponent(new PerfTestComponent1()); - const comp2 = entity.addComponent(new PerfTestComponent2()); - const comp3 = entity.addComponent(new PerfTestComponent3()); - - // 获取组件 - entity.getComponent(PerfTestComponent1); - entity.getComponent(PerfTestComponent2); - entity.getComponent(PerfTestComponent3); - - // 移除组件 - entity.removeComponent(comp1); - entity.removeComponent(comp2); - entity.removeComponent(comp3); - } - - const endTime = performance.now(); - const duration = endTime - startTime; - - console.log(`${iterations}次组件添加-获取-移除循环耗时: ${duration.toFixed(2)}ms`); - - expect(duration).toBeLessThan(70); - }); - }); - - describe('极端情况性能测试', () => { - test('单个组件高频访问性能', () => { - const entity = new Entity('SingleComponentEntity', 1); - entity.addComponent(new PerfTestComponent1()); - - const iterations = 50000; - const startTime = performance.now(); - - for (let i = 0; i < iterations; i++) { - entity.getComponent(PerfTestComponent1); - } - - const endTime = performance.now(); - const duration = endTime - startTime; - - console.log(`单组件${iterations}次高频访问耗时: ${duration.toFixed(2)}ms`); - - expect(duration).toBeLessThan(150); - }); - - test('多组件实体性能测试', () => { - const entity = new Entity('MultiComponentEntity', 1); - - // 添加8个组件(比典型情况多) - entity.addComponent(new PerfTestComponent1()); - entity.addComponent(new PerfTestComponent2()); - entity.addComponent(new PerfTestComponent3()); - entity.addComponent(new PerfTestComponent4()); - entity.addComponent(new PerfTestComponent5()); - entity.addComponent(new PerfTestComponent6()); - entity.addComponent(new PerfTestComponent7()); - entity.addComponent(new PerfTestComponent8()); - - const iterations = 5000; - const startTime = performance.now(); - - // 随机访问不同组件 - for (let i = 0; i < iterations; i++) { - entity.getComponent(PerfTestComponent1); - entity.getComponent(PerfTestComponent4); - entity.getComponent(PerfTestComponent7); - entity.getComponent(PerfTestComponent2); - entity.getComponent(PerfTestComponent8); - entity.getComponent(PerfTestComponent3); - entity.getComponent(PerfTestComponent6); - entity.getComponent(PerfTestComponent5); - } - - const endTime = performance.now(); - const duration = endTime - startTime; - - console.log(`多组件实体(8组件) ${iterations * 8}次随机访问耗时: ${duration.toFixed(2)}ms`); - - expect(duration).toBeLessThan(200); - }); - - test('hasComponent性能测试', () => { - const entity = new Entity('HasComponentTestEntity', 1); - - entity.addComponent(new PerfTestComponent1()); - entity.addComponent(new PerfTestComponent3()); - entity.addComponent(new PerfTestComponent5()); - - const iterations = 25000; // 减少迭代次数以适应CI环境 - const startTime = performance.now(); - - for (let i = 0; i < iterations; i++) { - entity.hasComponent(PerfTestComponent1); // 存在 - entity.hasComponent(PerfTestComponent2); // 不存在 - entity.hasComponent(PerfTestComponent3); // 存在 - entity.hasComponent(PerfTestComponent4); // 不存在 - entity.hasComponent(PerfTestComponent5); // 存在 - } - - const endTime = performance.now(); - const duration = endTime - startTime; - - console.log(`${iterations * 5}次hasComponent检查耗时: ${duration.toFixed(2)}ms`); - - expect(duration).toBeLessThan(310); - }); - }); - - describe('内存效率测试', () => { - test('大量实体内存使用测试', () => { - const entities: Entity[] = []; - const entityCount = 5000; - - const startTime = performance.now(); - - // 创建大量实体,模拟真实游戏场景 - for (let i = 0; i < entityCount; i++) { - const entity = new Entity(`Entity_${i}`, i); - - // 每个实体随机添加2-6个组件 - const componentCount = 2 + (i % 5); - if (componentCount >= 1) entity.addComponent(new PerfTestComponent1()); - if (componentCount >= 2) entity.addComponent(new PerfTestComponent2()); - if (componentCount >= 3) entity.addComponent(new PerfTestComponent3()); - if (componentCount >= 4) entity.addComponent(new PerfTestComponent4()); - if (componentCount >= 5) entity.addComponent(new PerfTestComponent5()); - if (componentCount >= 6) entity.addComponent(new PerfTestComponent6()); - - entities.push(entity); - } - - const creationTime = performance.now() - startTime; - - // 测试访问性能 - const accessStartTime = performance.now(); - - for (const entity of entities) { - entity.getComponent(PerfTestComponent1); - if (entity.hasComponent(PerfTestComponent3)) { - entity.getComponent(PerfTestComponent3); - } - if (entity.hasComponent(PerfTestComponent5)) { - entity.getComponent(PerfTestComponent5); - } - } - - const accessTime = performance.now() - accessStartTime; - - console.log(`创建${entityCount}个实体耗时: ${creationTime.toFixed(2)}ms`); - console.log(`访问${entityCount}个实体的组件耗时: ${accessTime.toFixed(2)}ms`); - - expect(creationTime).toBeLessThan(150); - expect(accessTime).toBeLessThan(100); - }); - }); -}); diff --git a/packages/core/tests/performance/EntityCreationPerformance.test.ts b/packages/core/tests/performance/EntityCreationPerformance.test.ts deleted file mode 100644 index 80e0fac8..00000000 --- a/packages/core/tests/performance/EntityCreationPerformance.test.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { EntityManager } from '../../src/ECS/Core/EntityManager'; -import { ComponentTypeManager } from '../../src/ECS/Utils/ComponentTypeManager'; - -describe('实体创建性能分析', () => { - let entityManager: EntityManager; - - beforeEach(() => { - ComponentTypeManager.instance.reset(); - entityManager = new EntityManager(); - }); - - test('性能分析:创建10000个实体', () => { - const entityCount = 10000; - console.log(`开始创建 ${entityCount} 个实体...`); - - // 预热 - for (let i = 0; i < 100; i++) { - entityManager.createEntity(`Warmup_${i}`); - } - // 重新创建EntityManager来清理 - entityManager = new EntityManager(); - - // 测试不同的创建方式 - console.log('\n=== 性能对比测试 ==='); - - // 1. 使用默认名称(包含Date.now()) - let startTime = performance.now(); - const entitiesWithDefaultName: any[] = []; - for (let i = 0; i < entityCount; i++) { - entitiesWithDefaultName.push(entityManager.createEntity()); - } - let endTime = performance.now(); - console.log(`1. 默认名称创建: ${(endTime - startTime).toFixed(2)}ms`); - entityManager = new EntityManager(); - - // 2. 使用预设名称(避免Date.now()) - startTime = performance.now(); - const entitiesWithPresetName: any[] = []; - for (let i = 0; i < entityCount; i++) { - entitiesWithPresetName.push(entityManager.createEntity(`Entity_${i}`)); - } - endTime = performance.now(); - console.log(`2. 预设名称创建: ${(endTime - startTime).toFixed(2)}ms`); - entityManager = new EntityManager(); - - // 3. 使用相同名称(减少字符串创建) - startTime = performance.now(); - const entitiesWithSameName: any[] = []; - const sameName = 'SameName'; - for (let i = 0; i < entityCount; i++) { - entitiesWithSameName.push(entityManager.createEntity(sameName)); - } - endTime = performance.now(); - console.log(`3. 相同名称创建: ${(endTime - startTime).toFixed(2)}ms`); - entityManager = new EntityManager(); - - // 4. 直接创建Entity对象(绕过EntityManager) - startTime = performance.now(); - const directEntities: any[] = []; - for (let i = 0; i < entityCount; i++) { - // 直接创建Entity,不通过EntityManager的复杂逻辑 - directEntities.push(new (require('../../src/ECS/Entity').Entity)(`Direct_${i}`, i)); - } - endTime = performance.now(); - console.log(`4. 直接创建Entity: ${(endTime - startTime).toFixed(2)}ms`); - - console.log('\n=== 性能分析结论 ==='); - console.log('如果相同名称创建明显更快,说明字符串操作是瓶颈'); - console.log('如果直接创建Entity更快,说明EntityManager的逻辑太重'); - }); - - test('详细分析EntityManager中的性能瓶颈', () => { - const entityCount = 1000; // 较小数量便于分析 - - console.log('\n=== 详细性能分析 ==='); - - // 分析各个步骤的耗时 - let totalTime = 0; - const stepTimes: Record = {}; - - for (let i = 0; i < entityCount; i++) { - const stepStart = performance.now(); - - // 模拟EntityManager.createEntity的各个步骤 - const name = `PerfTest_${i}`; - - // 步骤1: ID分配 - let stepTime = performance.now(); - const id = entityManager['_identifierPool'].checkOut(); - stepTimes['ID分配'] = (stepTimes['ID分配'] || 0) + (performance.now() - stepTime); - - // 步骤2: Entity创建 - stepTime = performance.now(); - const entity = new (require('../../src/ECS/Entity').Entity)(name, id); - stepTimes['Entity创建'] = (stepTimes['Entity创建'] || 0) + (performance.now() - stepTime); - - // 步骤3: 各种索引更新 - stepTime = performance.now(); - entityManager['_entities'].set(id, entity); - stepTimes['Map存储'] = (stepTimes['Map存储'] || 0) + (performance.now() - stepTime); - - stepTime = performance.now(); - entityManager['updateNameIndex'](entity, true); - stepTimes['名称索引'] = (stepTimes['名称索引'] || 0) + (performance.now() - stepTime); - - stepTime = performance.now(); - entityManager['updateTagIndex'](entity, true); - stepTimes['标签索引'] = (stepTimes['标签索引'] || 0) + (performance.now() - stepTime); - - stepTime = performance.now(); - entityManager['_componentIndexManager'].addEntity(entity); - stepTimes['组件索引'] = (stepTimes['组件索引'] || 0) + (performance.now() - stepTime); - - stepTime = performance.now(); - entityManager['_archetypeSystem'].addEntity(entity); - stepTimes['原型系统'] = (stepTimes['原型系统'] || 0) + (performance.now() - stepTime); - - stepTime = performance.now(); - entityManager['_dirtyTrackingSystem'].markDirty(entity, 1); // DirtyFlag.COMPONENT_ADDED - stepTimes['脏标记'] = (stepTimes['脏标记'] || 0) + (performance.now() - stepTime); - - stepTime = performance.now(); - // 跳过事件发射,因为它涉及复杂的对象创建 - stepTimes['其他'] = (stepTimes['其他'] || 0) + (performance.now() - stepTime); - - totalTime += (performance.now() - stepStart); - } - - console.log(`总耗时: ${totalTime.toFixed(2)}ms`); - console.log('各步骤平均耗时:'); - for (const [step, time] of Object.entries(stepTimes)) { - console.log(` ${step}: ${(time / entityCount * 1000).toFixed(3)}μs/entity`); - } - - // 找出最耗时的步骤 - const maxTime = Math.max(...Object.values(stepTimes)); - const slowestStep = Object.entries(stepTimes).find(([_, time]) => time === maxTime)?.[0]; - console.log(`最耗时的步骤: ${slowestStep} (${(maxTime / entityCount * 1000).toFixed(3)}μs/entity)`); - }); - - test('测试批量创建优化方案', () => { - const entityCount = 10000; - console.log(`\n=== 批量创建优化测试 ===`); - - // 当前方式:逐个创建 - let startTime = performance.now(); - for (let i = 0; i < entityCount; i++) { - entityManager.createEntity(`Current_${i}`); - } - let endTime = performance.now(); - const currentTime = endTime - startTime; - console.log(`当前方式: ${currentTime.toFixed(2)}ms`); - - entityManager = new EntityManager(); - - // 如果有批量创建方法的话... - // (这里只是演示概念,实际的批量创建需要在EntityManager中实现) - console.log('建议:实现批量创建方法,减少重复的索引更新和事件发射'); - }); - - test('验证批量创建优化效果', () => { - const entityCount = 10000; - console.log(`\n=== 批量创建优化效果验证 ===`); - - // 测试新的批量创建方法 - let startTime = performance.now(); - const batchEntities = entityManager.createEntitiesBatch(entityCount, "Batch", false); - let endTime = performance.now(); - const batchTime = endTime - startTime; - console.log(`批量创建(含事件): ${batchTime.toFixed(2)}ms`); - - entityManager = new EntityManager(); - - // 测试跳过事件的批量创建 - startTime = performance.now(); - const batchEntitiesNoEvents = entityManager.createEntitiesBatch(entityCount, "BatchNoEvents", true); - endTime = performance.now(); - const batchTimeNoEvents = endTime - startTime; - console.log(`批量创建(跳过事件): ${batchTimeNoEvents.toFixed(2)}ms`); - - entityManager = new EntityManager(); - - // 对比单个创建(使用优化后的createEntity) - startTime = performance.now(); - const singleEntities: any[] = []; - for (let i = 0; i < entityCount; i++) { - singleEntities.push(entityManager.createEntity(`Single_${i}`)); - } - endTime = performance.now(); - const singleTime = endTime - startTime; - console.log(`优化后单个创建: ${singleTime.toFixed(2)}ms`); - - console.log(`\n性能提升:`); - console.log(`批量创建 vs 单个创建: ${(singleTime / batchTime).toFixed(1)}x faster`); - console.log(`批量创建(跳过事件) vs 单个创建: ${(singleTime / batchTimeNoEvents).toFixed(1)}x faster`); - - // 验证功能正确性 - expect(batchEntities.length).toBe(entityCount); - expect(batchEntitiesNoEvents.length).toBe(entityCount); - expect(singleEntities.length).toBe(entityCount); - }); - - test('验证createEntity的Date.now()优化', () => { - console.log(`\n=== createEntity优化验证 ===`); - - const testCount = 1000; - - // 测试优化后的默认名称生成 - let startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - entityManager.createEntity(); // 使用优化后的计数器命名 - } - let endTime = performance.now(); - console.log(`计数器命名: ${(endTime - startTime).toFixed(2)}ms`); - - entityManager = new EntityManager(); - - // 对比:模拟使用Date.now()的方式 - startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - entityManager.createEntity(`Entity_${Date.now()}_${i}`); // 模拟原来的方式 - } - endTime = performance.now(); - console.log(`Date.now()命名: ${(endTime - startTime).toFixed(2)}ms`); - }); -}); \ No newline at end of file diff --git a/packages/core/tests/performance/InitializationComparison.performance.test.ts b/packages/core/tests/performance/InitializationComparison.performance.test.ts deleted file mode 100644 index 3e4b7563..00000000 --- a/packages/core/tests/performance/InitializationComparison.performance.test.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { Entity } from '../../src/ECS/Entity'; -import { BigIntFactory } from '../../src/ECS/Utils/BigIntCompatibility'; -import { ComponentType } from '../../src/ECS/Core/ComponentStorage'; - -describe('初始化方式性能对比', () => { - test('对比不同初始化方式的性能', () => { - const testCount = 10000; - console.log(`\n=== 初始化方式对比 (${testCount}个实体) ===`); - - // 方式1:字段直接初始化(原来的方式) - class EntityWithFieldInit { - public name: string; - public id: number; - private _componentMask = BigIntFactory.zero(); - private _componentTypeToIndex = new Map(); - - constructor(name: string, id: number) { - this.name = name; - this.id = id; - } - } - - // 方式2:构造函数初始化(新方式) - class EntityWithConstructorInit { - public name: string; - public id: number; - private _componentMask: any; - private _componentTypeToIndex: Map; - - constructor(name: string, id: number) { - this.name = name; - this.id = id; - this._componentMask = BigIntFactory.zero(); - this._componentTypeToIndex = new Map(); - } - } - - // 方式3:完全延迟初始化 - class EntityWithLazyInit { - public name: string; - public id: number; - private _componentMask: any; - private _componentTypeToIndex: Map | undefined; - - constructor(name: string, id: number) { - this.name = name; - this.id = id; - // 什么都不初始化 - } - - private ensureInit() { - if (!this._componentTypeToIndex) { - this._componentMask = BigIntFactory.zero(); - this._componentTypeToIndex = new Map(); - } - } - } - - // 测试方式1:字段直接初始化 - let startTime = performance.now(); - const entities1 = []; - for (let i = 0; i < testCount; i++) { - entities1.push(new EntityWithFieldInit(`Entity_${i}`, i)); - } - const fieldInitTime = performance.now() - startTime; - - // 测试方式2:构造函数初始化 - startTime = performance.now(); - const entities2 = []; - for (let i = 0; i < testCount; i++) { - entities2.push(new EntityWithConstructorInit(`Entity_${i}`, i)); - } - const constructorInitTime = performance.now() - startTime; - - // 测试方式3:延迟初始化 - startTime = performance.now(); - const entities3 = []; - for (let i = 0; i < testCount; i++) { - entities3.push(new EntityWithLazyInit(`Entity_${i}`, i)); - } - const lazyInitTime = performance.now() - startTime; - - // 测试方式4:只创建基本对象 - startTime = performance.now(); - const entities4 = []; - for (let i = 0; i < testCount; i++) { - entities4.push({ name: `Entity_${i}`, id: i }); - } - const basicObjectTime = performance.now() - startTime; - - console.log(`字段直接初始化: ${fieldInitTime.toFixed(2)}ms`); - console.log(`构造函数初始化: ${constructorInitTime.toFixed(2)}ms`); - console.log(`延迟初始化: ${lazyInitTime.toFixed(2)}ms`); - console.log(`基本对象创建: ${basicObjectTime.toFixed(2)}ms`); - - console.log(`\n性能对比:`); - console.log(`构造函数 vs 字段初始化: ${(fieldInitTime / constructorInitTime).toFixed(2)}x`); - console.log(`延迟 vs 构造函数: ${(constructorInitTime / lazyInitTime).toFixed(2)}x`); - console.log(`延迟 vs 基本对象: ${(lazyInitTime / basicObjectTime).toFixed(2)}x`); - }); - - test('测试BigIntFactory.zero()的性能', () => { - const testCount = 10000; - console.log(`\n=== BigIntFactory.zero()性能测试 ===`); - - // 测试1:每次调用BigIntFactory.zero() - let startTime = performance.now(); - const values1 = []; - for (let i = 0; i < testCount; i++) { - values1.push(BigIntFactory.zero()); - } - const directCallTime = performance.now() - startTime; - - // 测试2:重复使用同一个实例 - const sharedZero = BigIntFactory.zero(); - startTime = performance.now(); - const values2 = []; - for (let i = 0; i < testCount; i++) { - values2.push(sharedZero); - } - const sharedInstanceTime = performance.now() - startTime; - - // 测试3:使用数字0 - startTime = performance.now(); - const values3 = []; - for (let i = 0; i < testCount; i++) { - values3.push(0); - } - const numberZeroTime = performance.now() - startTime; - - console.log(`每次调用BigIntFactory.zero(): ${directCallTime.toFixed(2)}ms`); - console.log(`重复使用同一实例: ${sharedInstanceTime.toFixed(2)}ms`); - console.log(`使用数字0: ${numberZeroTime.toFixed(2)}ms`); - - console.log(`性能提升:`); - console.log(`共享实例 vs 每次调用: ${(directCallTime / sharedInstanceTime).toFixed(2)}x faster`); - console.log(`数字0 vs BigIntFactory: ${(directCallTime / numberZeroTime).toFixed(2)}x faster`); - }); - - test('测试Map创建的性能', () => { - const testCount = 10000; - console.log(`\n=== Map创建性能测试 ===`); - - // 测试1:每次new Map() - let startTime = performance.now(); - const maps1 = []; - for (let i = 0; i < testCount; i++) { - maps1.push(new Map()); - } - const newMapTime = performance.now() - startTime; - - // 测试2:使用对象字面量 - startTime = performance.now(); - const objects = []; - for (let i = 0; i < testCount; i++) { - objects.push({}); - } - const objectTime = performance.now() - startTime; - - // 测试3:延迟创建Map - startTime = performance.now(); - const lazyMaps = []; - for (let i = 0; i < testCount; i++) { - lazyMaps.push(null); // 先不创建 - } - const lazyTime = performance.now() - startTime; - - console.log(`每次new Map(): ${newMapTime.toFixed(2)}ms`); - console.log(`对象字面量: ${objectTime.toFixed(2)}ms`); - console.log(`延迟创建: ${lazyTime.toFixed(2)}ms`); - - console.log(`性能对比:`); - console.log(`对象 vs Map: ${(newMapTime / objectTime).toFixed(2)}x faster`); - console.log(`延迟 vs Map: ${(newMapTime / lazyTime).toFixed(2)}x faster`); - }); -}); \ No newline at end of file diff --git a/packages/core/tests/performance/Matcher.performance.test.ts b/packages/core/tests/performance/Matcher.performance.test.ts deleted file mode 100644 index dafed869..00000000 --- a/packages/core/tests/performance/Matcher.performance.test.ts +++ /dev/null @@ -1,341 +0,0 @@ -import { Component } from '../../src/ECS/Component'; -import { Matcher } from '../../src/ECS/Utils/Matcher'; - -class Position extends Component { - public x: number = 0; - public y: number = 0; - - constructor(...args: unknown[]) { - super(); - if (args.length >= 1) this.x = args[0] as number; - if (args.length >= 2) this.y = args[1] as number; - } -} - -class Velocity extends Component { - public vx: number = 0; - public vy: number = 0; - - constructor(...args: unknown[]) { - super(); - if (args.length >= 1) this.vx = args[0] as number; - if (args.length >= 2) this.vy = args[1] as number; - } -} - -class Health extends Component { - public hp: number = 100; - - constructor(...args: unknown[]) { - super(); - if (args.length >= 1) this.hp = args[0] as number; - } -} - -class Weapon extends Component { - public damage: number = 10; - - constructor(...args: unknown[]) { - super(); - if (args.length >= 1) this.damage = args[0] as number; - } -} - -describe('Matcher 性能测试', () => { - test('大量 Matcher 创建性能', () => { - console.log('\n=== Matcher 创建性能测试 ==='); - - const iterationCount = 10000; - - const staticStart = performance.now(); - for (let i = 0; i < iterationCount; i++) { - Matcher.all(Position, Velocity); - } - const staticTime = performance.now() - staticStart; - - const complexStart = performance.now(); - for (let i = 0; i < iterationCount; i++) { - Matcher.complex() - .all(Position, Velocity) - .any(Health, Weapon) - .none(Weapon); - } - const complexTime = performance.now() - complexStart; - - console.log(`静态方法创建: ${staticTime.toFixed(3)}ms (${(staticTime/iterationCount*1000).toFixed(3)}μs/次)`); - console.log(`复杂链式创建: ${complexTime.toFixed(3)}ms (${(complexTime/iterationCount*1000).toFixed(3)}μs/次)`); - - expect(staticTime).toBeLessThan(1000); - expect(complexTime).toBeLessThan(2000); - }); - - test('Matcher getCondition() 性能', () => { - console.log('\n=== getCondition() 性能测试 ==='); - - const matcher = Matcher.all(Position, Velocity, Health) - .any(Weapon) - .none(Health) - .withTag(123) - .withName('TestEntity') - .withComponent(Position); - - const iterationCount = 50000; - - const start = performance.now(); - for (let i = 0; i < iterationCount; i++) { - matcher.getCondition(); - } - const time = performance.now() - start; - - console.log(`getCondition() 调用: ${time.toFixed(3)}ms (${(time/iterationCount*1000).toFixed(3)}μs/次)`); - - expect(time).toBeLessThan(500); - }); - - test('Matcher clone() 性能', () => { - console.log('\n=== clone() 性能测试 ==='); - - const originalMatcher = Matcher.all(Position, Velocity, Health) - .any(Weapon) - .none(Health) - .withTag(123) - .withName('TestEntity') - .withComponent(Position); - - const iterationCount = 10000; - - const start = performance.now(); - for (let i = 0; i < iterationCount; i++) { - originalMatcher.clone(); - } - const time = performance.now() - start; - - console.log(`clone() 调用: ${time.toFixed(3)}ms (${(time/iterationCount*1000).toFixed(3)}μs/次)`); - - expect(time).toBeLessThan(1000); - }); - - test('Matcher toString() 性能', () => { - console.log('\n=== toString() 性能测试 ==='); - - const simpleMatcherStart = performance.now(); - const simpleMatcher = Matcher.all(Position); - for (let i = 0; i < 10000; i++) { - simpleMatcher.toString(); - } - const simpleTime = performance.now() - simpleMatcherStart; - - const complexMatcherStart = performance.now(); - const complexMatcher = Matcher.all(Position, Velocity, Health) - .any(Weapon) - .none(Health) - .withTag(123) - .withName('TestEntity') - .withComponent(Position); - for (let i = 0; i < 10000; i++) { - complexMatcher.toString(); - } - const complexTime = performance.now() - complexMatcherStart; - - console.log(`简单 toString(): ${simpleTime.toFixed(3)}ms (${(simpleTime/10000*1000).toFixed(3)}μs/次)`); - console.log(`复杂 toString(): ${complexTime.toFixed(3)}ms (${(complexTime/10000*1000).toFixed(3)}μs/次)`); - - expect(simpleTime).toBeLessThan(200); - expect(complexTime).toBeLessThan(500); - }); - - test('Matcher isEmpty() 性能', () => { - console.log('\n=== isEmpty() 性能测试 ==='); - - const emptyMatcher = Matcher.empty(); - const fullMatcher = Matcher.all(Position, Velocity) - .any(Health) - .none(Weapon) - .withTag(123); - - const iterationCount = 100000; - - const emptyStart = performance.now(); - for (let i = 0; i < iterationCount; i++) { - emptyMatcher.isEmpty(); - } - const emptyTime = performance.now() - emptyStart; - - const fullStart = performance.now(); - for (let i = 0; i < iterationCount; i++) { - fullMatcher.isEmpty(); - } - const fullTime = performance.now() - fullStart; - - console.log(`空匹配器 isEmpty(): ${emptyTime.toFixed(3)}ms (${(emptyTime/iterationCount*1000).toFixed(3)}μs/次)`); - console.log(`复杂匹配器 isEmpty(): ${fullTime.toFixed(3)}ms (${(fullTime/iterationCount*1000).toFixed(3)}μs/次)`); - - expect(emptyTime).toBeLessThan(100); - expect(fullTime).toBeLessThan(200); - }); - - test('Matcher reset() 性能', () => { - console.log('\n=== reset() 性能测试 ==='); - - const iterationCount = 50000; - - const start = performance.now(); - for (let i = 0; i < iterationCount; i++) { - const matcher = Matcher.all(Position, Velocity, Health) - .any(Weapon) - .none(Health) - .withTag(123) - .withName('TestEntity') - .withComponent(Position); - matcher.reset(); - } - const time = performance.now() - start; - - console.log(`reset() 调用: ${time.toFixed(3)}ms (${(time/iterationCount*1000).toFixed(3)}μs/次)`); - - expect(time).toBeLessThan(1000); - }); - - test('大规模链式调用性能', () => { - console.log('\n=== 大规模链式调用性能测试 ==='); - - const iterationCount = 5000; - - const start = performance.now(); - for (let i = 0; i < iterationCount; i++) { - Matcher.empty() - .all(Position) - .all(Velocity) - .all(Health) - .any(Weapon) - .any(Health) - .none(Weapon) - .none(Health) - .withTag(i) - .withName(`Entity${i}`) - .withComponent(Position) - .withoutTag() - .withoutName() - .withoutComponent() - .withTag(i * 2) - .withName(`NewEntity${i}`) - .withComponent(Velocity); - } - const time = performance.now() - start; - - console.log(`大规模链式调用: ${time.toFixed(3)}ms (${(time/iterationCount*1000).toFixed(3)}μs/次)`); - - expect(time).toBeLessThan(2000); - }); - - test('内存分配性能测试', () => { - console.log('\n=== 内存分配性能测试 ==='); - - const iterationCount = 10000; - const matchers: Matcher[] = []; - - const start = performance.now(); - for (let i = 0; i < iterationCount; i++) { - const matcher = Matcher.all(Position, Velocity) - .any(Health, Weapon) - .none(Health) - .withTag(i) - .withName(`Entity${i}`); - matchers.push(matcher); - } - const allocationTime = performance.now() - start; - - const cloneStart = performance.now(); - const clonedMatchers = matchers.map(m => m.clone()); - const cloneTime = performance.now() - cloneStart; - - const conditionStart = performance.now(); - const conditions = matchers.map(m => m.getCondition()); - const conditionTime = performance.now() - conditionStart; - - console.log(`创建 ${iterationCount} 个 Matcher: ${allocationTime.toFixed(3)}ms`); - console.log(`克隆 ${iterationCount} 个 Matcher: ${cloneTime.toFixed(3)}ms`); - console.log(`获取 ${iterationCount} 个条件: ${conditionTime.toFixed(3)}ms`); - - expect(allocationTime).toBeLessThan(1500); - expect(cloneTime).toBeLessThan(1000); - expect(conditionTime).toBeLessThan(500); - - expect(matchers.length).toBe(iterationCount); - expect(clonedMatchers.length).toBe(iterationCount); - expect(conditions.length).toBe(iterationCount); - }); - - test('字符串操作性能对比', () => { - console.log('\n=== 字符串操作性能对比 ==='); - - const simpleMatcher = Matcher.all(Position); - const complexMatcher = Matcher.all(Position, Velocity, Health, Weapon) - .any(Health, Weapon) - .none(Position, Velocity) - .withTag(123456) - .withName('VeryLongEntityNameForPerformanceTesting') - .withComponent(Health); - - const iterationCount = 10000; - - const simpleStart = performance.now(); - for (let i = 0; i < iterationCount; i++) { - simpleMatcher.toString(); - } - const simpleTime = performance.now() - simpleStart; - - const complexStart = performance.now(); - for (let i = 0; i < iterationCount; i++) { - complexMatcher.toString(); - } - const complexTime = performance.now() - complexStart; - - console.log(`简单匹配器字符串化: ${simpleTime.toFixed(3)}ms`); - console.log(`复杂匹配器字符串化: ${complexTime.toFixed(3)}ms`); - console.log(`复杂度影响: ${(complexTime/simpleTime).toFixed(2)}x`); - - expect(simpleTime).toBeLessThan(200); - expect(complexTime).toBeLessThan(800); - }); - - test('批量操作性能基准', () => { - console.log('\n=== 批量操作性能基准 ==='); - - const batchSize = 1000; - const operationCount = 10; - - const totalStart = performance.now(); - - for (let batch = 0; batch < operationCount; batch++) { - const matchers: Matcher[] = []; - - for (let i = 0; i < batchSize; i++) { - const matcher = Matcher.complex() - .all(Position, Velocity) - .any(Health, Weapon) - .withTag(batch * batchSize + i); - - matchers.push(matcher); - } - - matchers.forEach(m => { - m.getCondition(); - m.toString(); - m.isEmpty(); - }); - - const cloned = matchers.map(m => m.clone()); - cloned.forEach(m => m.reset()); - } - - const totalTime = performance.now() - totalStart; - const totalOperations = batchSize * operationCount * 5; // 每个matcher执行5个操作 - - console.log(`批量操作总时间: ${totalTime.toFixed(3)}ms`); - console.log(`总操作数: ${totalOperations}`); - console.log(`平均每操作: ${(totalTime/totalOperations*1000).toFixed(3)}μs`); - - expect(totalTime).toBeLessThan(5000); - }); -}); \ No newline at end of file diff --git a/packages/core/tests/performance/OptimizedPerformanceAnalysis.performance.test.ts b/packages/core/tests/performance/OptimizedPerformanceAnalysis.performance.test.ts deleted file mode 100644 index 47018f31..00000000 --- a/packages/core/tests/performance/OptimizedPerformanceAnalysis.performance.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { EntityManager } from '../../src/ECS/Core/EntityManager'; -import { ComponentTypeManager } from '../../src/ECS/Utils/ComponentTypeManager'; -import { Entity } from '../../src/ECS/Entity'; - -describe('优化后的性能分析 - ComponentIndexManager优化', () => { - let entityManager: EntityManager; - - beforeEach(() => { - ComponentTypeManager.instance.reset(); - entityManager = new EntityManager(); - }); - - test('测试优化后的实体创建性能', () => { - const testCount = 10000; - console.log(`\n=== 优化后的实体创建性能测试 (${testCount}个实体) ===`); - - const startTime = performance.now(); - const entities = []; - - for (let i = 0; i < testCount; i++) { - entities.push(entityManager.createEntity(`Entity_${i}`)); - } - - const totalTime = performance.now() - startTime; - const avgTime = totalTime / testCount; - - console.log(`总耗时: ${totalTime.toFixed(2)}ms`); - console.log(`平均每个实体: ${avgTime.toFixed(3)}ms`); - console.log(`每秒创建实体数: ${Math.round(1000 / avgTime)}`); - - if (totalTime < 140) { - console.log(`✅ 性能优化成功!实际耗时 ${totalTime.toFixed(2)}ms < 140ms 目标`); - } else { - console.log(`❌ 仍需进一步优化,实际耗时 ${totalTime.toFixed(2)}ms >= 140ms 目标`); - } - - // 性能基准:应该在140ms以下 - expect(totalTime).toBeLessThan(200); // 放宽一些给CI环境 - }); - - test('对比批量创建与逐个创建的性能', () => { - const testCount = 5000; - console.log(`\n=== 批量创建vs逐个创建对比 (${testCount}个实体) ===`); - - // 逐个创建 - let startTime = performance.now(); - for (let i = 0; i < testCount; i++) { - entityManager.createEntity(`Individual_${i}`); - } - const individualTime = performance.now() - startTime; - - // 重置管理器 - entityManager = new EntityManager(); - - // 批量创建 - startTime = performance.now(); - entityManager.createEntitiesBatch(testCount, "Batch", false); - const batchTime = performance.now() - startTime; - - // 重置管理器 - entityManager = new EntityManager(); - - // 批量创建(跳过事件) - startTime = performance.now(); - entityManager.createEntitiesBatch(testCount, "BatchNoEvents", true); - const batchNoEventsTime = performance.now() - startTime; - - console.log(`逐个创建: ${individualTime.toFixed(2)}ms`); - console.log(`批量创建: ${batchTime.toFixed(2)}ms`); - console.log(`批量创建(跳过事件): ${batchNoEventsTime.toFixed(2)}ms`); - console.log(`批量优化倍数: ${(individualTime / batchTime).toFixed(2)}x`); - console.log(`跳过事件优化倍数: ${(individualTime / batchNoEventsTime).toFixed(2)}x`); - }); - - test('测试组件索引管理器对空实体的优化效果', () => { - const testCount = 10000; - console.log(`\n=== 空实体优化效果测试 (${testCount}个空实体) ===`); - - const startTime = performance.now(); - const entities = []; - - for (let i = 0; i < testCount; i++) { - const entity = entityManager.createEntity(`EmptyEntity_${i}`); - entities.push(entity); - } - - const totalTime = performance.now() - startTime; - - // 验证前几个实体确实没有组件 - for (let i = 0; i < Math.min(5, entities.length); i++) { - expect(entities[i].components.length).toBe(0); - } - - console.log(`空实体创建总耗时: ${totalTime.toFixed(2)}ms`); - console.log(`平均每个空实体: ${(totalTime / testCount).toFixed(3)}ms`); - - // 获取优化统计信息 - const stats = entityManager.getOptimizationStats(); - console.log(`组件索引统计:`, stats.componentIndex); - - // 空实体创建应该非常快,放宽限制以适应CI环境 - expect(totalTime).toBeLessThan(150); - }); - - test('测试Set对象池的效果', () => { - const testCount = 1000; - console.log(`\n=== Set对象池效果测试 (${testCount}次添加/删除) ===`); - - // 创建实体 - const entities = []; - for (let i = 0; i < testCount; i++) { - entities.push(entityManager.createEntity(`PoolTest_${i}`)); - } - - // 测试删除和重新创建的性能 - const startTime = performance.now(); - - // 删除一半实体 - for (let i = 0; i < testCount / 2; i++) { - entityManager.destroyEntity(entities[i]); - } - - // 重新创建实体 - for (let i = 0; i < testCount / 2; i++) { - entityManager.createEntity(`RecycledEntity_${i}`); - } - - const totalTime = performance.now() - startTime; - - console.log(`删除+重新创建耗时: ${totalTime.toFixed(2)}ms`); - console.log(`平均每次操作: ${(totalTime / testCount).toFixed(3)}ms`); - - // 对象池优化应该让重复操作更快,放宽限制适应不同环境 - expect(totalTime).toBeLessThan(100); - }); - - test('内存使用量分析', () => { - const testCount = 5000; - console.log(`\n=== 内存使用量分析 (${testCount}个实体) ===`); - - // 获取初始内存使用情况 - const initialStats = entityManager.getOptimizationStats(); - const initialMemory = initialStats.componentIndex.memoryUsage; - - // 创建实体 - const entities = []; - for (let i = 0; i < testCount; i++) { - entities.push(entityManager.createEntity(`MemoryTest_${i}`)); - } - - // 获取创建后的内存使用情况 - const afterStats = entityManager.getOptimizationStats(); - const afterMemory = afterStats.componentIndex.memoryUsage; - - console.log(`初始内存使用: ${initialMemory} 字节`); - console.log(`创建后内存使用: ${afterMemory} 字节`); - console.log(`增加的内存: ${afterMemory - initialMemory} 字节`); - console.log(`平均每个实体内存: ${((afterMemory - initialMemory) / testCount).toFixed(2)} 字节`); - - // 清理并观察内存回收 - for (const entity of entities) { - entityManager.destroyEntity(entity); - } - - const cleanupStats = entityManager.getOptimizationStats(); - const cleanupMemory = cleanupStats.componentIndex.memoryUsage; - - console.log(`清理后内存使用: ${cleanupMemory} 字节`); - console.log(`内存回收率: ${(((afterMemory - cleanupMemory) / (afterMemory - initialMemory)) * 100).toFixed(1)}%`); - }); -}); \ No newline at end of file