archetypesystem只负责原型管理,querysytem负责查询和缓存

This commit is contained in:
YHH
2025-09-29 11:01:39 +08:00
parent d62bf9f7f9
commit be11060674
2 changed files with 54 additions and 117 deletions

View File

@@ -15,12 +15,8 @@ export interface Archetype {
id: ArchetypeId; id: ArchetypeId;
/** 包含的组件类型 */ /** 包含的组件类型 */
componentTypes: ComponentType[]; componentTypes: ComponentType[];
/** 属于该原型的实体列表 */ /** 属于该原型的实体集合 */
entities: Entity[]; entities: Set<Entity>;
/** 原型创建时间 */
createdAt: number;
/** 最后更新时间 */
updatedAt: number;
} }
/** /**
@@ -31,10 +27,6 @@ export interface ArchetypeQueryResult {
archetypes: Archetype[]; archetypes: Archetype[];
/** 所有匹配实体的总数 */ /** 所有匹配实体的总数 */
totalEntities: number; totalEntities: number;
/** 查询执行时间(毫秒) */
executionTime: number;
/** 是否使用了缓存 */
fromCache: boolean;
} }
/** /**
@@ -45,21 +37,18 @@ export interface ArchetypeQueryResult {
export class ArchetypeSystem { export class ArchetypeSystem {
/** 所有原型的映射表 */ /** 所有原型的映射表 */
private _archetypes = new Map<ArchetypeId, Archetype>(); private _archetypes = new Map<ArchetypeId, Archetype>();
/** 实体到原型的映射 */ /** 实体到原型的映射 */
private _entityToArchetype = new Map<Entity, Archetype>(); private _entityToArchetype = new Map<Entity, Archetype>();
/** 组件类型到原型的映射 */ /** 组件类型到原型的映射 */
private _componentToArchetypes = new Map<ComponentType, Set<Archetype>>(); private _componentToArchetypes = new Map<ComponentType, Set<Archetype>>();
/** 查询缓存 */ /** 实体组件类型缓存 */
private _queryCache = new Map<string, { private _entityComponentTypesCache = new Map<Entity, ComponentType[]>();
result: ArchetypeQueryResult;
timestamp: number; /** 原型ID缓存 */
}>(); private _archetypeIdCache = new Map<string, ArchetypeId>();
private _cacheTimeout = 5000;
private _maxCacheSize = 100;
/** /**
* 添加实体到原型系统 * 添加实体到原型系统
@@ -67,18 +56,16 @@ export class ArchetypeSystem {
public addEntity(entity: Entity): void { public addEntity(entity: Entity): void {
const componentTypes = this.getEntityComponentTypes(entity); const componentTypes = this.getEntityComponentTypes(entity);
const archetypeId = this.generateArchetypeId(componentTypes); const archetypeId = this.generateArchetypeId(componentTypes);
let archetype = this._archetypes.get(archetypeId); let archetype = this._archetypes.get(archetypeId);
if (!archetype) { if (!archetype) {
archetype = this.createArchetype(componentTypes); archetype = this.createArchetype(componentTypes);
} }
archetype.entities.push(entity); archetype.entities.add(entity);
archetype.updatedAt = Date.now();
this._entityToArchetype.set(entity, archetype); this._entityToArchetype.set(entity, archetype);
this.updateComponentIndexes(archetype, componentTypes, true); this.updateComponentIndexes(archetype, componentTypes, true);
this.invalidateQueryCache();
} }
/** /**
@@ -88,14 +75,11 @@ export class ArchetypeSystem {
const archetype = this._entityToArchetype.get(entity); const archetype = this._entityToArchetype.get(entity);
if (!archetype) return; if (!archetype) return;
const index = archetype.entities.indexOf(entity); archetype.entities.delete(entity);
if (index !== -1) {
archetype.entities.splice(index, 1);
archetype.updatedAt = Date.now();
}
// 清理实体相关缓存
this._entityComponentTypesCache.delete(entity);
this._entityToArchetype.delete(entity); this._entityToArchetype.delete(entity);
this.invalidateQueryCache();
} }
/** /**
@@ -108,6 +92,9 @@ export class ArchetypeSystem {
*/ */
public updateEntity(entity: Entity): void { public updateEntity(entity: Entity): void {
const currentArchetype = this._entityToArchetype.get(entity); const currentArchetype = this._entityToArchetype.get(entity);
// 清理实体组件类型缓存,强制重新计算
this._entityComponentTypesCache.delete(entity);
const newComponentTypes = this.getEntityComponentTypes(entity); const newComponentTypes = this.getEntityComponentTypes(entity);
const newArchetypeId = this.generateArchetypeId(newComponentTypes); const newArchetypeId = this.generateArchetypeId(newComponentTypes);
@@ -116,13 +103,12 @@ export class ArchetypeSystem {
return; return;
} }
const affectedComponentTypes = new Set<ComponentType>();
// 从旧原型中移除实体 // 从旧原型中移除实体
if (currentArchetype) { if (currentArchetype) {
const index = currentArchetype.entities.indexOf(entity); currentArchetype.entities.delete(entity);
if (index !== -1) { currentArchetype.componentTypes.forEach(type => affectedComponentTypes.add(type));
currentArchetype.entities.splice(index, 1);
currentArchetype.updatedAt = Date.now();
}
} }
// 获取或创建新原型 // 获取或创建新原型
@@ -132,9 +118,9 @@ export class ArchetypeSystem {
} }
// 将实体添加到新原型 // 将实体添加到新原型
newArchetype.entities.push(entity); newArchetype.entities.add(entity);
newArchetype.updatedAt = Date.now();
this._entityToArchetype.set(entity, newArchetype); this._entityToArchetype.set(entity, newArchetype);
newComponentTypes.forEach(type => affectedComponentTypes.add(type));
// 更新组件索引 // 更新组件索引
if (currentArchetype) { if (currentArchetype) {
@@ -142,27 +128,12 @@ export class ArchetypeSystem {
} }
this.updateComponentIndexes(newArchetype, newComponentTypes, true); this.updateComponentIndexes(newArchetype, newComponentTypes, true);
// 使查询缓存失效
this.invalidateQueryCache();
} }
/** /**
* 查询包含指定组件组合的原型 * 查询包含指定组件组合的原型
*/ */
public queryArchetypes(componentTypes: ComponentType[], operation: 'AND' | 'OR' = 'AND'): ArchetypeQueryResult { public queryArchetypes(componentTypes: ComponentType[], operation: 'AND' | 'OR' = 'AND'): ArchetypeQueryResult {
const startTime = performance.now();
const cacheKey = `${operation}:${componentTypes.map(t => getComponentTypeName(t)).sort().join(',')}`;
// 检查缓存
const cached = this._queryCache.get(cacheKey);
if (cached && (Date.now() - cached.timestamp < this._cacheTimeout)) {
return {
...cached.result,
executionTime: performance.now() - startTime,
fromCache: true
};
}
const matchingArchetypes: Archetype[] = []; const matchingArchetypes: Archetype[] = [];
let totalEntities = 0; let totalEntities = 0;
@@ -171,7 +142,7 @@ export class ArchetypeSystem {
for (const archetype of this._archetypes.values()) { for (const archetype of this._archetypes.values()) {
if (this.archetypeContainsAllComponents(archetype, componentTypes)) { if (this.archetypeContainsAllComponents(archetype, componentTypes)) {
matchingArchetypes.push(archetype); matchingArchetypes.push(archetype);
totalEntities += archetype.entities.length; totalEntities += archetype.entities.size;
} }
} }
} else { } else {
@@ -188,24 +159,14 @@ export class ArchetypeSystem {
for (const archetype of foundArchetypes) { for (const archetype of foundArchetypes) {
matchingArchetypes.push(archetype); matchingArchetypes.push(archetype);
totalEntities += archetype.entities.length; totalEntities += archetype.entities.size;
} }
} }
const result: ArchetypeQueryResult = { return {
archetypes: matchingArchetypes, archetypes: matchingArchetypes,
totalEntities, totalEntities
executionTime: performance.now() - startTime,
fromCache: false
}; };
// 缓存结果
this._queryCache.set(cacheKey, {
result,
timestamp: Date.now()
});
return result;
} }
/** /**
@@ -229,24 +190,38 @@ export class ArchetypeSystem {
this._archetypes.clear(); this._archetypes.clear();
this._entityToArchetype.clear(); this._entityToArchetype.clear();
this._componentToArchetypes.clear(); this._componentToArchetypes.clear();
this._queryCache.clear(); this._entityComponentTypesCache.clear();
this._archetypeIdCache.clear();
} }
/** /**
* 获取实体的组件类型列表 * 获取实体的组件类型列表
*/ */
private getEntityComponentTypes(entity: Entity): ComponentType[] { private getEntityComponentTypes(entity: Entity): ComponentType[] {
return entity.components.map(component => component.constructor as ComponentType); let componentTypes = this._entityComponentTypesCache.get(entity);
if (!componentTypes) {
componentTypes = entity.components.map(component => component.constructor as ComponentType);
this._entityComponentTypesCache.set(entity, componentTypes);
}
return componentTypes;
} }
/** /**
* 生成原型ID * 生成原型ID
*/ */
private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId { private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId {
return componentTypes // 创建缓存键
const cacheKey = componentTypes
.map(type => getComponentTypeName(type)) .map(type => getComponentTypeName(type))
.sort() .sort()
.join('|'); .join('|');
let archetypeId = this._archetypeIdCache.get(cacheKey);
if (!archetypeId) {
archetypeId = cacheKey;
this._archetypeIdCache.set(cacheKey, archetypeId);
}
return archetypeId;
} }
/** /**
@@ -258,9 +233,7 @@ export class ArchetypeSystem {
const archetype: Archetype = { const archetype: Archetype = {
id, id,
componentTypes: [...componentTypes], componentTypes: [...componentTypes],
entities: [], entities: new Set<Entity>()
createdAt: Date.now(),
updatedAt: Date.now()
}; };
this._archetypes.set(id, archetype); this._archetypes.set(id, archetype);
@@ -301,10 +274,5 @@ export class ArchetypeSystem {
} }
} }
/**
* 使查询缓存失效
*/
private invalidateQueryCache(): void {
this._queryCache.clear();
}
} }

View File

@@ -66,13 +66,6 @@ interface QueryCacheEntry {
* 高性能实体查询系统 * 高性能实体查询系统
* *
* 提供快速的实体查询功能,支持按组件类型、标签、名称等多种方式查询实体。 * 提供快速的实体查询功能,支持按组件类型、标签、名称等多种方式查询实体。
* 系统采用多级索引和智能缓存机制,确保在大量实体场景下的查询性能。
*
* 主要特性:
* - 支持单组件和多组件查询
* - 自动索引管理和缓存优化
* - WebAssembly计算加速如果可用
* - 详细的性能统计信息
* *
* @example * @example
* ```typescript * ```typescript
@@ -96,12 +89,8 @@ export class QuerySystem {
private cacheMaxSize = 1000; private cacheMaxSize = 1000;
private cacheTimeout = 5000; // 5秒缓存过期 private cacheTimeout = 5000; // 5秒缓存过期
// 性能优化缓存
private componentNameCache = new WeakMap<ComponentType, string>();
private cacheKeyCache = new Map<string, string>();
private componentMaskCache = new Map<string, BitMask64Data>(); private componentMaskCache = new Map<string, BitMask64Data>();
// 新增性能优化系统
private componentIndexManager: ComponentIndexManager; private componentIndexManager: ComponentIndexManager;
private archetypeSystem: ArchetypeSystem; private archetypeSystem: ArchetypeSystem;
@@ -862,7 +851,6 @@ export class QuerySystem {
*/ */
private clearQueryCache(): void { private clearQueryCache(): void {
this.queryCache.clear(); this.queryCache.clear();
this.cacheKeyCache.clear();
this.componentMaskCache.clear(); this.componentMaskCache.clear();
} }
@@ -872,34 +860,19 @@ export class QuerySystem {
private generateCacheKey(prefix: string, componentTypes: ComponentType[]): string { private generateCacheKey(prefix: string, componentTypes: ComponentType[]): string {
// 快速路径:单组件查询 // 快速路径:单组件查询
if (componentTypes.length === 1) { if (componentTypes.length === 1) {
let name = this.componentNameCache.get(componentTypes[0]); const name = getComponentTypeName(componentTypes[0]);
if (!name) {
name = getComponentTypeName(componentTypes[0]);
this.componentNameCache.set(componentTypes[0], name);
}
return `${prefix}:${name}`; return `${prefix}:${name}`;
} }
// 多组件查询:使用排序后的类型名称创建键 // 多组件查询:使用排序后的类型名称创建键
const sortKey = componentTypes.map(t => { const sortKey = componentTypes.map(t => {
let name = this.componentNameCache.get(t); const name = getComponentTypeName(t);
if (!name) {
name = getComponentTypeName(t);
this.componentNameCache.set(t, name);
}
return name; return name;
}).sort().join(','); }).sort().join(',');
const fullKey = `${prefix}:${sortKey}`; const fullKey = `${prefix}:${sortKey}`;
// 检查缓存的键是否已存在 return fullKey;
let cachedKey = this.cacheKeyCache.get(fullKey);
if (!cachedKey) {
cachedKey = fullKey;
this.cacheKeyCache.set(fullKey, cachedKey);
}
return cachedKey;
} }
/** /**
@@ -923,11 +896,7 @@ export class QuerySystem {
private createComponentMask(componentTypes: ComponentType[]): BitMask64Data { private createComponentMask(componentTypes: ComponentType[]): BitMask64Data {
// 生成缓存键 // 生成缓存键
const cacheKey = componentTypes.map(t => { const cacheKey = componentTypes.map(t => {
let name = this.componentNameCache.get(t); const name = getComponentTypeName(t);
if (!name) {
name = getComponentTypeName(t);
this.componentNameCache.set(t, name);
}
return name; return name;
}).sort().join(','); }).sort().join(',');
@@ -1026,7 +995,7 @@ export class QuerySystem {
archetypeSystem: this.archetypeSystem.getAllArchetypes().map(a => ({ archetypeSystem: this.archetypeSystem.getAllArchetypes().map(a => ({
id: a.id, id: a.id,
componentTypes: a.componentTypes.map(t => getComponentTypeName(t)), componentTypes: a.componentTypes.map(t => getComponentTypeName(t)),
entityCount: a.entities.length entityCount: a.entities.size
})) }))
}, },
cacheStats: { cacheStats: {