Skip to content

Commit 1d11792

Browse files
committed
refactor(query): cache wildcard types and simplify getEntities
Pre-compute wildcard component types in constructor to avoid repeated filtering and getDetailedIdType calls on each getEntities invocation. Extract entity wildcard checking into dedicated helper method.
1 parent 00fa51d commit 1d11792

File tree

1 file changed

+34
-36
lines changed

1 file changed

+34
-36
lines changed

src/query/query.ts

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ export class Query {
1414
private filter: QueryFilter;
1515
private cachedArchetypes: Archetype[] = [];
1616
private isDisposed = false;
17+
/** Cached wildcard component types for faster entity filtering */
18+
private wildcardTypes: WildcardRelationId<any>[];
1719

1820
constructor(world: World, componentTypes: EntityId<any>[], filter: QueryFilter = {}) {
1921
this.world = world;
2022
this.componentTypes = [...componentTypes].sort((a, b) => a - b);
2123
this.filter = filter;
24+
// Pre-compute wildcard types once
25+
this.wildcardTypes = this.componentTypes.filter(
26+
(ct) => getDetailedIdType(ct).type === "wildcard-relation",
27+
) as WildcardRelationId<any>[];
2228
this.updateCache();
2329
// Register with world for archetype updates
2430
world._registerQuery(this);
@@ -38,48 +44,43 @@ export class Query {
3844
*/
3945
getEntities(): EntityId[] {
4046
this.ensureNotDisposed();
41-
const result: EntityId[] = [];
42-
43-
// Check if any component types are wildcard relations
44-
const hasWildcardRelations = this.componentTypes.some((ct) => {
45-
const detailed = getDetailedIdType(ct);
46-
return detailed.type === "wildcard-relation";
47-
});
4847

49-
// If there are wildcard relations, we need to filter entities that actually have them
50-
// This is necessary for dontFragment components where an archetype can contain entities
51-
// with and without the relation
52-
if (hasWildcardRelations) {
53-
for (const archetype of this.cachedArchetypes) {
54-
for (const entity of archetype.getEntities()) {
55-
// Check if entity has all required wildcard relations
56-
let hasAllRelations = true;
57-
for (const componentType of this.componentTypes) {
58-
const detailed = getDetailedIdType(componentType);
59-
if (detailed.type === "wildcard-relation") {
60-
// Check if entity has at least one relation matching this wildcard
61-
const relations = archetype.get(entity, componentType as WildcardRelationId<any>);
62-
if (!relations || relations.length === 0) {
63-
hasAllRelations = false;
64-
break;
65-
}
66-
}
67-
}
68-
if (hasAllRelations) {
69-
result.push(entity);
70-
}
71-
}
72-
}
73-
} else {
74-
// No wildcard relations, can just return all entities from matching archetypes
48+
// Fast path: no wildcard relations
49+
if (this.wildcardTypes.length === 0) {
50+
const result: EntityId[] = [];
7551
for (const archetype of this.cachedArchetypes) {
7652
result.push(...archetype.getEntities());
7753
}
54+
return result;
7855
}
7956

57+
// Slow path: need to filter entities that actually have wildcard relations
58+
// This is necessary for dontFragment components where an archetype can contain
59+
// entities with and without the relation
60+
const result: EntityId[] = [];
61+
for (const archetype of this.cachedArchetypes) {
62+
for (const entity of archetype.getEntities()) {
63+
if (this.entityHasAllWildcards(archetype, entity)) {
64+
result.push(entity);
65+
}
66+
}
67+
}
8068
return result;
8169
}
8270

71+
/**
72+
* Check if entity has all required wildcard relations
73+
*/
74+
private entityHasAllWildcards(archetype: Archetype, entity: EntityId): boolean {
75+
for (const wildcardType of this.wildcardTypes) {
76+
const relations = archetype.get(entity, wildcardType);
77+
if (!relations || relations.length === 0) {
78+
return false;
79+
}
80+
}
81+
return true;
82+
}
83+
8384
/**
8485
* Get entities with their component data
8586
* @param componentTypes Array of component types to retrieve
@@ -188,9 +189,6 @@ export class Query {
188189
}
189190
}
190191

191-
/**
192-
* Dispose the query and disconnect from world
193-
*/
194192
/**
195193
* Request disposal of this query.
196194
* This will decrement the world's reference count for the query.

0 commit comments

Comments
 (0)