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,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`);
});
});