archetypesystem只负责原型管理,querysytem负责查询和缓存
This commit is contained in:
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,14 +44,11 @@ export class ArchetypeSystem {
|
|||||||
/** 组件类型到原型的映射 */
|
/** 组件类型到原型的映射 */
|
||||||
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;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
private _cacheTimeout = 5000;
|
/** 原型ID缓存 */
|
||||||
private _maxCacheSize = 100;
|
private _archetypeIdCache = new Map<string, ArchetypeId>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加实体到原型系统
|
* 添加实体到原型系统
|
||||||
@@ -73,12 +62,10 @@ export class ArchetypeSystem {
|
|||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
Reference in New Issue
Block a user