Skip to content

Commit

Permalink
#1295 Reduce number of observers created for queries
Browse files Browse the repository at this point in the history
* Catch more script errors in parser

* Fix issue with anonymous template instance creation

* Fix issues with partial component assignments in flecs script

* Fix issues with assigning non-trivial components in flecs script

* Reduce number of observers created for table events
  • Loading branch information
SanderMertens authored Aug 8, 2024
1 parent 6f694d0 commit b6181db
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
32 changes: 32 additions & 0 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14444,6 +14444,20 @@ int flecs_multi_observer_init(
}
}

/* If an observer is only interested in table events, we only need to
* observe a single component, as each table event will be emitted for all
* components of the source table. */
bool only_table_events = true;
for (i = 0; i < o->event_count; i ++) {
ecs_entity_t e = o->events[i];
if (e != EcsOnTableCreate && e != EcsOnTableDelete &&
e != EcsOnTableEmpty && e != EcsOnTableFill)
{
only_table_events = false;
break;
}
}

if (query->flags & EcsQueryMatchPrefab) {
child_desc.query.flags |= EcsQueryMatchPrefab;
}
Expand All @@ -14452,6 +14466,7 @@ int flecs_multi_observer_init(
child_desc.query.flags |= EcsQueryMatchDisabled;
}

bool self_term_handled = false;
for (i = 0; i < term_count; i ++) {
if (query->terms[i].inout == EcsInOutFilter) {
continue;
Expand All @@ -14464,6 +14479,23 @@ int flecs_multi_observer_init(
int16_t oper = term->oper;
ecs_id_t id = term->id;

if (only_table_events) {
/* For table event observers, only observe a single $this|self
* term. Make sure to create observers for non-self terms, as those
* require event propagation. */
if (ecs_term_match_this(term) &&
(term->src.id & EcsTraverseFlags) == EcsSelf)
{
if (oper == EcsAnd) {
if (!self_term_handled) {
self_term_handled = true;
} else {
continue;
}
}
}
}

/* AndFrom & OrFrom terms insert multiple observers */
if (oper == EcsAndFrom || oper == EcsOrFrom) {
const ecs_type_t *type = ecs_get_type(world, id);
Expand Down
32 changes: 32 additions & 0 deletions src/observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,20 @@ int flecs_multi_observer_init(
}
}

/* If an observer is only interested in table events, we only need to
* observe a single component, as each table event will be emitted for all
* components of the source table. */
bool only_table_events = true;
for (i = 0; i < o->event_count; i ++) {
ecs_entity_t e = o->events[i];
if (e != EcsOnTableCreate && e != EcsOnTableDelete &&
e != EcsOnTableEmpty && e != EcsOnTableFill)
{
only_table_events = false;
break;
}
}

if (query->flags & EcsQueryMatchPrefab) {
child_desc.query.flags |= EcsQueryMatchPrefab;
}
Expand All @@ -761,6 +775,7 @@ int flecs_multi_observer_init(
child_desc.query.flags |= EcsQueryMatchDisabled;
}

bool self_term_handled = false;
for (i = 0; i < term_count; i ++) {
if (query->terms[i].inout == EcsInOutFilter) {
continue;
Expand All @@ -773,6 +788,23 @@ int flecs_multi_observer_init(
int16_t oper = term->oper;
ecs_id_t id = term->id;

if (only_table_events) {
/* For table event observers, only observe a single $this|self
* term. Make sure to create observers for non-self terms, as those
* require event propagation. */
if (ecs_term_match_this(term) &&
(term->src.id & EcsTraverseFlags) == EcsSelf)
{
if (oper == EcsAnd) {
if (!self_term_handled) {
self_term_handled = true;
} else {
continue;
}
}
}
}

/* AndFrom & OrFrom terms insert multiple observers */
if (oper == EcsAndFrom || oper == EcsOrFrom) {
const ecs_type_t *type = ecs_get_type(world, id);
Expand Down

0 comments on commit b6181db

Please sign in to comment.