From 7190f50495c22d63338404bfaed056549b1e1bf5 Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Thu, 25 Jun 2026 10:49:14 -0700 Subject: [PATCH 1/3] [queries] Skip op context allocation for cached queries without compiled ops --- distr/flecs.c | 4 +++- distr/flecs_no_addons.c | 4 +++- src/query/engine/eval_iter.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/distr/flecs.c b/distr/flecs.c index 77e55d7988..c4ab25dcfb 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -85722,7 +85722,9 @@ ecs_iter_t flecs_query_iter( if (op_count) { qit->written = flecs_iter_calloc_n(&it, ecs_write_flags_t, op_count); - qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); + if (impl->ops || !impl->cache) { + qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); + } } #ifdef FLECS_DEBUG diff --git a/distr/flecs_no_addons.c b/distr/flecs_no_addons.c index e564967f63..8dabaf8a0f 100644 --- a/distr/flecs_no_addons.c +++ b/distr/flecs_no_addons.c @@ -48023,7 +48023,9 @@ ecs_iter_t flecs_query_iter( if (op_count) { qit->written = flecs_iter_calloc_n(&it, ecs_write_flags_t, op_count); - qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); + if (impl->ops || !impl->cache) { + qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); + } } #ifdef FLECS_DEBUG diff --git a/src/query/engine/eval_iter.c b/src/query/engine/eval_iter.c index b9192a4051..be4e675735 100644 --- a/src/query/engine/eval_iter.c +++ b/src/query/engine/eval_iter.c @@ -549,7 +549,9 @@ ecs_iter_t flecs_query_iter( if (op_count) { qit->written = flecs_iter_calloc_n(&it, ecs_write_flags_t, op_count); - qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); + if (impl->ops || !impl->cache) { + qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); + } } #ifdef FLECS_DEBUG From 8a165afb2803a18a134f4f07de945215568ccf2a Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Thu, 25 Jun 2026 10:50:09 -0700 Subject: [PATCH 2/3] [queries] Allocate iterator vars and written arrays in a single block --- distr/flecs.c | 14 ++++++++------ distr/flecs_no_addons.c | 14 ++++++++------ src/query/engine/eval_iter.c | 14 ++++++++------ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/distr/flecs.c b/distr/flecs.c index c4ab25dcfb..b9fb4f10e7 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -85716,15 +85716,17 @@ ecs_iter_t flecs_query_iter( flecs_query_cache_iter_init(&it, qit, impl); + ecs_size_t vars_size = var_count * ECS_SIZEOF(ecs_var_t); + ecs_size_t written_size = op_count * ECS_SIZEOF(ecs_write_flags_t); + char *scratch = flecs_iter_calloc( + &it, vars_size + written_size, ECS_ALIGNOF(ecs_var_t)); if (var_count) { - qit->vars = flecs_iter_calloc_n(&it, ecs_var_t, var_count); + qit->vars = (ecs_var_t*)(void*)scratch; } + qit->written = (ecs_write_flags_t*)(void*)(scratch + vars_size); - if (op_count) { - qit->written = flecs_iter_calloc_n(&it, ecs_write_flags_t, op_count); - if (impl->ops || !impl->cache) { - qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); - } + if (impl->ops || !impl->cache) { + qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); } #ifdef FLECS_DEBUG diff --git a/distr/flecs_no_addons.c b/distr/flecs_no_addons.c index 8dabaf8a0f..ec45f79b51 100644 --- a/distr/flecs_no_addons.c +++ b/distr/flecs_no_addons.c @@ -48017,15 +48017,17 @@ ecs_iter_t flecs_query_iter( flecs_query_cache_iter_init(&it, qit, impl); + ecs_size_t vars_size = var_count * ECS_SIZEOF(ecs_var_t); + ecs_size_t written_size = op_count * ECS_SIZEOF(ecs_write_flags_t); + char *scratch = flecs_iter_calloc( + &it, vars_size + written_size, ECS_ALIGNOF(ecs_var_t)); if (var_count) { - qit->vars = flecs_iter_calloc_n(&it, ecs_var_t, var_count); + qit->vars = (ecs_var_t*)(void*)scratch; } + qit->written = (ecs_write_flags_t*)(void*)(scratch + vars_size); - if (op_count) { - qit->written = flecs_iter_calloc_n(&it, ecs_write_flags_t, op_count); - if (impl->ops || !impl->cache) { - qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); - } + if (impl->ops || !impl->cache) { + qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); } #ifdef FLECS_DEBUG diff --git a/src/query/engine/eval_iter.c b/src/query/engine/eval_iter.c index be4e675735..ba6a83087b 100644 --- a/src/query/engine/eval_iter.c +++ b/src/query/engine/eval_iter.c @@ -543,15 +543,17 @@ ecs_iter_t flecs_query_iter( flecs_query_cache_iter_init(&it, qit, impl); + ecs_size_t vars_size = var_count * ECS_SIZEOF(ecs_var_t); + ecs_size_t written_size = op_count * ECS_SIZEOF(ecs_write_flags_t); + char *scratch = flecs_iter_calloc( + &it, vars_size + written_size, ECS_ALIGNOF(ecs_var_t)); if (var_count) { - qit->vars = flecs_iter_calloc_n(&it, ecs_var_t, var_count); + qit->vars = (ecs_var_t*)(void*)scratch; } + qit->written = (ecs_write_flags_t*)(void*)(scratch + vars_size); - if (op_count) { - qit->written = flecs_iter_calloc_n(&it, ecs_write_flags_t, op_count); - if (impl->ops || !impl->cache) { - qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); - } + if (impl->ops || !impl->cache) { + qit->op_ctx = flecs_iter_calloc_n(&it, ecs_query_op_ctx_t, op_count); } #ifdef FLECS_DEBUG From ab21046ffcd25c3582de30ac94597e8de4da5095 Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Thu, 25 Jun 2026 11:31:54 -0700 Subject: [PATCH 3/3] [pipelines] Remove unused iters and iter_count members from pipeline state --- distr/flecs.c | 11 ----------- distr/flecs_no_addons.c | 2 -- src/addons/pipeline/pipeline.c | 7 ------- src/addons/pipeline/pipeline.h | 2 -- src/addons/stats/memory.c | 2 -- 5 files changed, 24 deletions(-) diff --git a/distr/flecs.c b/distr/flecs.c index b9fb4f10e7..ce30b18099 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -28150,8 +28150,6 @@ struct ecs_pipeline_state_t { ecs_entity_t last_system; /* Last system run by pipeline */ int32_t match_count; /* Used to track if rebuild is necessary */ int32_t rebuild_count; /* Number of pipeline rebuilds */ - ecs_iter_t *iters; /* Iterator for worker(s) */ - int32_t iter_count; /* Members for continuing pipeline iteration after pipeline rebuild */ ecs_pipeline_op_t *cur_op; /* Current pipeline op */ @@ -62670,7 +62668,6 @@ static void flecs_pipeline_state_free( ecs_allocator_t *a = &world->allocator; ecs_vec_fini_t(a, &p->ops, ecs_pipeline_op_t); ecs_vec_fini_t(a, &p->systems, ecs_system_t*); - ecs_os_free(p->iters); ecs_os_free(p); } } @@ -63162,12 +63159,6 @@ bool flecs_pipeline_update( bool rebuilt = flecs_pipeline_build(world, pq); if (start_of_frame) { - /* Initialize iterators */ - int32_t i, count = pq->iter_count; - for (i = 0; i < count; i ++) { - ecs_world_t *stage = ecs_get_stage(world, i); - pq->iters[i] = ecs_query_iter(stage, pq->query); - } pq->cur_op = ecs_vec_first_t(&pq->ops, ecs_pipeline_op_t); pq->cur_i = 0; } else { @@ -74939,8 +74930,6 @@ void flecs_pipeline_memory_get( ECS_SIZEOF(ecs_pipeline_op_t); result->bytes_pipelines += ecs_vec_size(&ps->systems) * ECS_SIZEOF(ecs_entity_t); - result->bytes_pipelines += ps->iter_count * - ECS_SIZEOF(ecs_iter_t); } } } diff --git a/distr/flecs_no_addons.c b/distr/flecs_no_addons.c index ec45f79b51..f73b0fcb59 100644 --- a/distr/flecs_no_addons.c +++ b/distr/flecs_no_addons.c @@ -23907,8 +23907,6 @@ struct ecs_pipeline_state_t { ecs_entity_t last_system; /* Last system run by pipeline */ int32_t match_count; /* Used to track if rebuild is necessary */ int32_t rebuild_count; /* Number of pipeline rebuilds */ - ecs_iter_t *iters; /* Iterator for worker(s) */ - int32_t iter_count; /* Members for continuing pipeline iteration after pipeline rebuild */ ecs_pipeline_op_t *cur_op; /* Current pipeline op */ diff --git a/src/addons/pipeline/pipeline.c b/src/addons/pipeline/pipeline.c index 3a1943c03f..921a6b248a 100644 --- a/src/addons/pipeline/pipeline.c +++ b/src/addons/pipeline/pipeline.c @@ -19,7 +19,6 @@ static void flecs_pipeline_state_free( ecs_allocator_t *a = &world->allocator; ecs_vec_fini_t(a, &p->ops, ecs_pipeline_op_t); ecs_vec_fini_t(a, &p->systems, ecs_system_t*); - ecs_os_free(p->iters); ecs_os_free(p); } } @@ -511,12 +510,6 @@ bool flecs_pipeline_update( bool rebuilt = flecs_pipeline_build(world, pq); if (start_of_frame) { - /* Initialize iterators */ - int32_t i, count = pq->iter_count; - for (i = 0; i < count; i ++) { - ecs_world_t *stage = ecs_get_stage(world, i); - pq->iters[i] = ecs_query_iter(stage, pq->query); - } pq->cur_op = ecs_vec_first_t(&pq->ops, ecs_pipeline_op_t); pq->cur_i = 0; } else { diff --git a/src/addons/pipeline/pipeline.h b/src/addons/pipeline/pipeline.h index e7543bacfd..a68e4f9a5a 100644 --- a/src/addons/pipeline/pipeline.h +++ b/src/addons/pipeline/pipeline.h @@ -27,8 +27,6 @@ struct ecs_pipeline_state_t { ecs_entity_t last_system; /* Last system run by pipeline */ int32_t match_count; /* Used to track if rebuild is necessary */ int32_t rebuild_count; /* Number of pipeline rebuilds */ - ecs_iter_t *iters; /* Iterator for worker(s) */ - int32_t iter_count; /* Members for continuing pipeline iteration after pipeline rebuild */ ecs_pipeline_op_t *cur_op; /* Current pipeline op */ diff --git a/src/addons/stats/memory.c b/src/addons/stats/memory.c index b953c19aba..dddfd75d81 100644 --- a/src/addons/stats/memory.c +++ b/src/addons/stats/memory.c @@ -791,8 +791,6 @@ void flecs_pipeline_memory_get( ECS_SIZEOF(ecs_pipeline_op_t); result->bytes_pipelines += ecs_vec_size(&ps->systems) * ECS_SIZEOF(ecs_entity_t); - result->bytes_pipelines += ps->iter_count * - ECS_SIZEOF(ecs_iter_t); } } }