From c4da2c2b02e966b766f46883bfce4fec2a4e94aa Mon Sep 17 00:00:00 2001 From: Ukendio Date: Mon, 30 Jun 2025 00:22:48 +0200 Subject: [PATCH] Optimize removal path --- jecs.luau | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/jecs.luau b/jecs.luau index 214b066..866cb10 100755 --- a/jecs.luau +++ b/jecs.luau @@ -2582,15 +2582,41 @@ local function world_new() archetype_destroy(world, idr_archetype) end else - for archetype_id in idr.records do - local idr_archetype = archetypes[archetype_id] - local entities = idr_archetype.entities - local n = #entities - for i = n, 1, -1 do - inner_world_remove(world, entities[i], entity) - end + local on_remove = idr.hooks.on_remove + if on_remove then + for archetype_id in idr.records do + local idr_archetype = archetypes[archetype_id] + local to = archetype_traverse_remove(world, entity, idr_archetype) + local entities = idr_archetype.entities + local n = #entities + for i = n, 1, -1 do + local e = entities[i] + on_remove(e, entity) + local r = eindex_sparse_array[ECS_ID(e :: number)] + local from = r.archetype + if from ~= idr_archetype then + -- unfortunately the on_remove hook allows a window where `e` can have changed archetype + -- this is hypothetically not that expensive of an operation anyways + to = archetype_traverse_remove(world, entity, from) + end + entity_move(entity_index, e, r, to) + end - archetype_destroy(world, idr_archetype) + archetype_destroy(world, idr_archetype) + end + else + for archetype_id in idr.records do + local idr_archetype = archetypes[archetype_id] + local to = archetype_traverse_remove(world, entity, idr_archetype) + local entities = idr_archetype.entities + local n = #entities + for i = n, 1, -1 do + local e = entities[i] + entity_move(entity_index, e, eindex_sparse_array[ECS_ID(e :: number)], to) + end + + archetype_destroy(world, idr_archetype) + end end end end