- 为 zero() 和 one() 方法添加缓存,避免重复创建对象 ComponentIndexManager 优化 - 添加了空实体检查,跳过不必要的索引操作 - 实现了 Set 对象池,重用 Set 实例以减少内存分配 - 优化了自动优化检查频率,从每次操作变为每100次操作检查一次 EntityManager 优化 - 对空实体跳过不必要的组件索引、原型系统和脏标记操作 - 批量创建时同样应用空实体优化
176 lines
6.8 KiB
TypeScript
176 lines
6.8 KiB
TypeScript
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`);
|
||
});
|
||
}); |