BigIntFactory 缓存优化

- 为 zero() 和 one() 方法添加缓存,避免重复创建对象
ComponentIndexManager 优化
  - 添加了空实体检查,跳过不必要的索引操作
  - 实现了 Set 对象池,重用 Set 实例以减少内存分配
  - 优化了自动优化检查频率,从每次操作变为每100次操作检查一次
EntityManager 优化
  - 对空实体跳过不必要的组件索引、原型系统和脏标记操作
  - 批量创建时同样应用空实体优化
This commit is contained in:
YHH
2025-07-30 17:10:58 +08:00
parent 69ec545854
commit f3dc8c6344
7 changed files with 929 additions and 15 deletions

View File

@@ -0,0 +1,302 @@
import { EntityManager } from '../../../src/ECS/Core/EntityManager';
import { ComponentTypeManager } from '../../../src/ECS/Utils/ComponentTypeManager';
import { Entity } from '../../../src/ECS/Entity';
import { Component } from '../../../src/ECS/Component';
// 测试用组件
class TestComponent extends Component {
constructor(public value: number = 0) {
super();
}
}
class AnotherTestComponent extends Component {
constructor(public name: string = 'test') {
super();
}
}
describe('ComponentIndexManager功能测试', () => {
let entityManager: EntityManager;
beforeEach(() => {
ComponentTypeManager.instance.reset();
entityManager = new EntityManager();
});
describe('基本功能测试', () => {
test('应该能够正确创建空实体', () => {
const entity = entityManager.createEntity('TestEntity');
expect(entity).toBeDefined();
expect(entity.name).toBe('TestEntity');
expect(entity.components.length).toBe(0);
expect(entity.id).toBeGreaterThanOrEqual(0);
});
test('应该能够正确管理实体的组件索引', () => {
const entity = entityManager.createEntity('TestEntity');
const component = new TestComponent(42);
// 添加组件前
expect(entity.hasComponent(TestComponent)).toBe(false);
// 添加组件
entity.addComponent(component);
// 添加组件后
expect(entity.hasComponent(TestComponent)).toBe(true);
expect(entity.getComponent(TestComponent)).toBe(component);
expect(entity.components.length).toBe(1);
});
test('应该能够正确处理组件查询', () => {
const entity1 = entityManager.createEntity('Entity1');
const entity2 = entityManager.createEntity('Entity2');
entity1.addComponent(new TestComponent(1));
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test2'));
// 查询包含TestComponent的实体
const entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(2);
expect(entitiesWithTest).toContain(entity1);
expect(entitiesWithTest).toContain(entity2);
// 查询包含AnotherTestComponent的实体
const entitiesWithAnother = entityManager.getEntitiesWithComponent(AnotherTestComponent);
expect(entitiesWithAnother).toHaveLength(1);
expect(entitiesWithAnother).toContain(entity2);
});
test('应该能够正确处理复杂查询', () => {
const entity1 = entityManager.createEntity('Entity1');
const entity2 = entityManager.createEntity('Entity2');
const entity3 = entityManager.createEntity('Entity3');
// entity1: TestComponent
entity1.addComponent(new TestComponent(1));
// entity2: TestComponent + AnotherTestComponent
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test2'));
// entity3: AnotherTestComponent
entity3.addComponent(new AnotherTestComponent('test3'));
// AND查询同时包含两个组件的实体
const bothComponents = entityManager.queryWithComponentIndex(
[TestComponent, AnotherTestComponent],
'AND'
);
expect(bothComponents.size).toBe(1);
expect(bothComponents.has(entity2)).toBe(true);
// OR查询包含任一组件的实体
const eitherComponent = entityManager.queryWithComponentIndex(
[TestComponent, AnotherTestComponent],
'OR'
);
expect(eitherComponent.size).toBe(3);
expect(eitherComponent.has(entity1)).toBe(true);
expect(eitherComponent.has(entity2)).toBe(true);
expect(eitherComponent.has(entity3)).toBe(true);
});
});
describe('组件移除功能测试', () => {
test('应该能够正确移除组件并更新索引', () => {
const entity = entityManager.createEntity('TestEntity');
const component = new TestComponent(42);
// 添加组件
entity.addComponent(component);
expect(entity.hasComponent(TestComponent)).toBe(true);
// 移除组件
entity.removeComponent(component);
expect(entity.hasComponent(TestComponent)).toBe(false);
expect(entity.getComponent(TestComponent)).toBeNull();
expect(entity.components.length).toBe(0);
// 索引应该被正确更新
const entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(0);
});
test('应该能够正确处理实体销毁', () => {
const entity = entityManager.createEntity('TestEntity');
entity.addComponent(new TestComponent(42));
// 确认实体存在且有组件
expect(entityManager.getEntity(entity.id)).toBe(entity);
expect(entityManager.getEntitiesWithComponent(TestComponent)).toHaveLength(1);
// 销毁实体
const destroyed = entityManager.destroyEntity(entity);
expect(destroyed).toBe(true);
// 确认实体被正确销毁
expect(entityManager.getEntity(entity.id)).toBeNull();
expect(entityManager.getEntitiesWithComponent(TestComponent)).toHaveLength(0);
});
});
describe('批量操作功能测试', () => {
test('应该能够正确处理批量创建实体', () => {
const entities = entityManager.createEntitiesBatch(5, 'BatchEntity');
expect(entities).toHaveLength(5);
entities.forEach((entity, index) => {
expect(entity.name).toMatch(/^BatchEntity_\d+$/);
expect(entity.components.length).toBe(0);
expect(entityManager.getEntity(entity.id)).toBe(entity);
});
expect(entityManager.entityCount).toBe(5);
});
test('批量创建的实体应该有正确的索引', () => {
const entities = entityManager.createEntitiesBatch(3, 'IndexTest');
// 给第一个和第三个实体添加组件
entities[0].addComponent(new TestComponent(1));
entities[2].addComponent(new TestComponent(3));
const entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(2);
expect(entitiesWithTest).toContain(entities[0]);
expect(entitiesWithTest).toContain(entities[2]);
});
});
describe('查询构建器功能测试', () => {
test('应该能够使用查询构建器进行复杂查询', () => {
const entity1 = entityManager.createEntity('Active1');
const entity2 = entityManager.createEntity('Active2');
const entity3 = entityManager.createEntity('Inactive');
entity1.addComponent(new TestComponent(1));
entity1.active = true;
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test2'));
entity2.active = true;
entity3.addComponent(new TestComponent(3));
entity3.active = false;
// 查询激活状态且包含TestComponent的实体
const activeWithTest = entityManager.query()
.withAll(TestComponent)
.active()
.execute();
expect(activeWithTest).toHaveLength(2);
expect(activeWithTest).toContain(entity1);
expect(activeWithTest).toContain(entity2);
expect(activeWithTest).not.toContain(entity3);
// 查询同时包含两个组件的实体
const withBothComponents = entityManager.query()
.withAll(TestComponent, AnotherTestComponent)
.execute();
expect(withBothComponents).toHaveLength(1);
expect(withBothComponents).toContain(entity2);
});
test('查询构建器应该支持自定义过滤条件', () => {
const entity1 = entityManager.createEntity('Player1');
const entity2 = entityManager.createEntity('Enemy1');
const entity3 = entityManager.createEntity('Player2');
entity1.addComponent(new TestComponent(100));
entity2.addComponent(new TestComponent(50));
entity3.addComponent(new TestComponent(200));
// 查询名称以"Player"开头且TestComponent值大于150的实体
const strongPlayers = entityManager.query()
.withAll(TestComponent)
.where(entity => entity.name.startsWith('Player'))
.where(entity => {
const testComp = entity.getComponent(TestComponent);
return testComp !== null && testComp.value > 150;
})
.execute();
expect(strongPlayers).toHaveLength(1);
expect(strongPlayers).toContain(entity3);
});
});
describe('统计信息功能测试', () => {
test('应该能够获取正确的统计信息', () => {
// 创建一些实体和组件
const entity1 = entityManager.createEntity('StatTest1');
const entity2 = entityManager.createEntity('StatTest2');
entity1.addComponent(new TestComponent(1));
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test'));
const stats = entityManager.getOptimizationStats();
expect(stats).toBeDefined();
expect(stats.componentIndex).toBeDefined();
expect(stats.componentIndex.type).toBe('hash');
expect(stats.archetypeSystem).toBeDefined();
expect(stats.dirtyTracking).toBeDefined();
});
test('应该能够正确统计实体数量', () => {
expect(entityManager.entityCount).toBe(0);
expect(entityManager.activeEntityCount).toBe(0);
const entity1 = entityManager.createEntity('Count1');
const entity2 = entityManager.createEntity('Count2');
expect(entityManager.entityCount).toBe(2);
expect(entityManager.activeEntityCount).toBe(2);
entity1.active = false;
expect(entityManager.activeEntityCount).toBe(1);
entityManager.destroyEntity(entity2);
expect(entityManager.entityCount).toBe(1);
expect(entityManager.activeEntityCount).toBe(0);
});
});
describe('边界情况测试', () => {
test('应该能够处理空组件列表的查询', () => {
const entity = entityManager.createEntity('EmptyTest');
const emptyQuery = entityManager.queryWithComponentIndex([], 'AND');
expect(emptyQuery.size).toBe(0);
const emptyOrQuery = entityManager.queryWithComponentIndex([], 'OR');
expect(emptyOrQuery.size).toBe(0);
});
test('应该能够处理不存在的组件类型查询', () => {
class NonExistentComponent extends Component {}
const entities = entityManager.getEntitiesWithComponent(NonExistentComponent);
expect(entities).toHaveLength(0);
});
test('应该能够处理重复添加相同组件类型', () => {
const entity = entityManager.createEntity('DuplicateTest');
const component1 = new TestComponent(1);
const component2 = new TestComponent(2);
entity.addComponent(component1);
expect(() => entity.addComponent(component2)).toThrow();
// 第一个组件应该仍然存在
expect(entity.getComponent(TestComponent)).toBe(component1);
});
});
});

View File

@@ -0,0 +1,227 @@
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)`);
});
});

View File

@@ -0,0 +1,176 @@
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<ComponentType, number>();
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<ComponentType, number>;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
this._componentMask = BigIntFactory.zero();
this._componentTypeToIndex = new Map<ComponentType, number>();
}
}
// 方式3完全延迟初始化
class EntityWithLazyInit {
public name: string;
public id: number;
private _componentMask: any;
private _componentTypeToIndex: Map<ComponentType, number> | 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<ComponentType, number>();
}
}
}
// 测试方式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`);
});
});

View File

@@ -0,0 +1,171 @@
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)}%`);
});
});