improve performance of the clone operations

This commit is contained in:
BlackMATov
2025-11-19 08:51:26 +07:00
parent 55e444ca63
commit de73881f63
2 changed files with 161 additions and 283 deletions

View File

@@ -11,6 +11,8 @@
- We can return deferred status from modifying operations and spawn/clone methods.
- We should have a way to not copy components on deferred spawn/clone.
- We can cache default/duplicate per chunk to speed up entity creation with setup hooks.
- We need spawn/clone fuzzy tests!
## Known Issues

View File

@@ -2055,34 +2055,40 @@ function __spawn_entity(chunk, entity, components)
local fragment_default, fragment_duplicate =
__evolved_get(component_fragment, __DEFAULT, __DUPLICATE)
local new_component = components[component_fragment]
local ini_component = components[component_fragment]
if new_component == nil then
new_component = fragment_default
if ini_component == nil then
ini_component = fragment_default
end
if new_component ~= nil and fragment_duplicate then
new_component = fragment_duplicate(new_component)
end
if ini_component ~= nil and fragment_duplicate then
local new_component = fragment_duplicate(ini_component)
if new_component == nil then
new_component = true
end
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
component_storage[place] = new_component
else
if ini_component == nil then
ini_component = true
end
component_storage[place] = ini_component
end
end
else
for component_index = 1, chunk_component_count do
local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
local new_component = components[component_fragment]
local ini_component = components[component_fragment]
if new_component == nil then
new_component = true
if ini_component == nil then
ini_component = true
end
component_storage[place] = new_component
component_storage[place] = ini_component
end
end
@@ -2206,20 +2212,29 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
local fragment_default, fragment_duplicate =
__evolved_get(component_fragment, __DEFAULT, __DUPLICATE)
if fragment_duplicate then
local ini_component = components[component_fragment]
if ini_component == nil then
ini_component = fragment_default
end
if ini_component ~= nil and fragment_duplicate then
for place = b_place, e_place do
local new_component = components[component_fragment]
if new_component == nil then new_component = fragment_default end
if new_component ~= nil then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end
local new_component = fragment_duplicate(ini_component)
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
end
else
local new_component = components[component_fragment]
if new_component == nil then new_component = fragment_default end
if new_component == nil then new_component = true end
if ini_component == nil then
ini_component = true
end
for place = b_place, e_place do
component_storage[place] = new_component
component_storage[place] = ini_component
end
end
end
@@ -2228,10 +2243,14 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
local new_component = components[component_fragment]
if new_component == nil then new_component = true end
local ini_component = components[component_fragment]
if ini_component == nil then
ini_component = true
end
for place = b_place, e_place do
component_storage[place] = new_component
component_storage[place] = ini_component
end
end
end
@@ -2312,8 +2331,12 @@ function __clone_entity(prefab, entity, components)
prefab_chunk.__without_unique_fragments = __chunk_without_unique_fragments(prefab_chunk)
end
if not prefab_chunk or not prefab_chunk.__without_unique_fragments then
return __spawn_entity(nil, entity, components)
end
local chunk = __chunk_with_components(
prefab_chunk and prefab_chunk.__without_unique_fragments,
prefab_chunk.__without_unique_fragments,
components)
if not chunk then
@@ -2324,9 +2347,6 @@ function __clone_entity(prefab, entity, components)
local req_fragment_list
local req_fragment_count = 0
local ini_chunk = chunk
local ini_fragment_set = ini_chunk.__fragment_set
if chunk.__has_required_fragments then
---@type table<evolved.fragment, integer>
req_fragment_set = __acquire_table(__table_pool_tag.fragment_set)
@@ -2334,7 +2354,7 @@ function __clone_entity(prefab, entity, components)
---@type evolved.fragment[]
req_fragment_list = __acquire_table(__table_pool_tag.fragment_list)
req_fragment_count = __chunk_required_fragments(ini_chunk,
req_fragment_count = __chunk_required_fragments(chunk,
req_fragment_set, req_fragment_list, req_fragment_count)
for req_fragment_index = 1, req_fragment_count do
@@ -2346,8 +2366,13 @@ function __clone_entity(prefab, entity, components)
local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count
local chunk_component_count = chunk.__component_count
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
local chunk_component_fragments = chunk.__component_fragments
local prefab_component_indices = prefab_chunk.__component_indices
local prefab_component_storages = prefab_chunk.__component_storages
local place = chunk_entity_count + 1
@@ -2362,144 +2387,69 @@ function __clone_entity(prefab, entity, components)
__entity_places[entity_primary] = place
end
if prefab_chunk then
local prefab_component_count = prefab_chunk.__component_count
local prefab_component_storages = prefab_chunk.__component_storages
local prefab_component_fragments = prefab_chunk.__component_fragments
if prefab_chunk.__has_setup_hooks then
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
---@type evolved.duplicate?
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place]
local new_component = prefab_component
if new_component ~= nil and fragment_duplicate then
new_component = fragment_duplicate(new_component)
end
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
end
end
else
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place]
local new_component = prefab_component
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
end
end
end
end
if chunk.__has_setup_hooks then
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
for component_index = 1, chunk_component_count do
local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
if component_index then
local component_storage = chunk_component_storages[component_index]
---@type evolved.default?, evolved.duplicate?
local fragment_default, fragment_duplicate =
__evolved_get(component_fragment, __DEFAULT, __DUPLICATE)
---@type evolved.duplicate?
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
local ini_component = components[component_fragment]
local new_component = component
if new_component ~= nil and fragment_duplicate then
new_component = fragment_duplicate(new_component)
if ini_component == nil then
if chunk == prefab_chunk then
ini_component = component_storage[prefab_place]
else
local prefab_component_index = prefab_component_indices[component_fragment]
if prefab_component_index then
local prefab_component_storage = prefab_component_storages[prefab_component_index]
ini_component = prefab_component_storage[prefab_place]
else
ini_component = fragment_default
end
end
end
if ini_component ~= nil and fragment_duplicate then
local new_component = fragment_duplicate(ini_component)
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
---@type evolved.default?, evolved.duplicate?
local req_fragment_default, req_fragment_duplicate =
__evolved_get(req_fragment, __DEFAULT, __DUPLICATE)
local req_component = req_fragment_default
if req_component ~= nil and req_fragment_duplicate then
req_component = req_fragment_duplicate(req_component)
end
if req_component == nil then
req_component = true
end
req_component_storage[place] = req_component
if ini_component == nil then
ini_component = true
end
component_storage[place] = ini_component
end
end
else
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
for component_index = 1, chunk_component_count do
local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
if component_index then
local component_storage = chunk_component_storages[component_index]
local ini_component = components[component_fragment]
local new_component = component
if new_component == nil then new_component = true end
component_storage[place] = new_component
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
local req_component = true
req_component_storage[place] = req_component
if ini_component == nil then
if chunk == prefab_chunk then
ini_component = component_storage[prefab_place]
else
local prefab_component_index = prefab_component_indices[component_fragment]
if prefab_component_index then
local prefab_component_storage = prefab_component_storages[prefab_component_index]
ini_component = prefab_component_storage[prefab_place]
else
ini_component = true
end
end
end
component_storage[place] = ini_component
end
end
@@ -2564,8 +2514,12 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
prefab_chunk.__without_unique_fragments = __chunk_without_unique_fragments(prefab_chunk)
end
if not prefab_chunk or not prefab_chunk.__without_unique_fragments then
return __multi_spawn_entity(nil, entity_list, entity_count, components)
end
local chunk = __chunk_with_components(
prefab_chunk and prefab_chunk.__without_unique_fragments,
prefab_chunk.__without_unique_fragments,
components)
if not chunk then
@@ -2576,9 +2530,6 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
local req_fragment_list
local req_fragment_count = 0
local ini_chunk = chunk
local ini_fragment_set = ini_chunk.__fragment_set
if chunk.__has_required_fragments then
---@type table<evolved.fragment, integer>
req_fragment_set = __acquire_table(__table_pool_tag.fragment_set)
@@ -2586,7 +2537,7 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
---@type evolved.fragment[]
req_fragment_list = __acquire_table(__table_pool_tag.fragment_list)
req_fragment_count = __chunk_required_fragments(ini_chunk,
req_fragment_count = __chunk_required_fragments(chunk,
req_fragment_set, req_fragment_list, req_fragment_count)
for req_fragment_index = 1, req_fragment_count do
@@ -2598,8 +2549,13 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count
local chunk_component_count = chunk.__component_count
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
local chunk_component_fragments = chunk.__component_fragments
local prefab_component_indices = prefab_chunk.__component_indices
local prefab_component_storages = prefab_chunk.__component_storages
local b_place = chunk_entity_count + 1
local e_place = chunk_entity_count + entity_count
@@ -2621,155 +2577,75 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
end
end
if prefab_chunk then
local prefab_component_count = prefab_chunk.__component_count
local prefab_component_storages = prefab_chunk.__component_storages
local prefab_component_fragments = prefab_chunk.__component_fragments
if prefab_chunk.__has_setup_hooks then
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
---@type evolved.duplicate?
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place]
if fragment_duplicate then
for place = b_place, e_place do
local new_component = prefab_component
if new_component ~= nil then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end
component_storage[place] = new_component
end
else
local new_component = prefab_component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
end
else
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place]
local new_component = prefab_component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
end
end
if chunk.__has_setup_hooks then
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
for component_index = 1, chunk_component_count do
local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
if component_index then
local component_storage = chunk_component_storages[component_index]
---@type evolved.default?, evolved.duplicate?
local fragment_default, fragment_duplicate =
__evolved_get(component_fragment, __DEFAULT, __DUPLICATE)
---@type evolved.duplicate?
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
local ini_component = components[component_fragment]
if fragment_duplicate then
for place = b_place, e_place do
local new_component = component
if new_component ~= nil then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end
component_storage[place] = new_component
end
if ini_component == nil then
if chunk == prefab_chunk then
ini_component = component_storage[prefab_place]
else
local new_component = component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
local prefab_component_index = prefab_component_indices[component_fragment]
if prefab_component_index then
local prefab_component_storage = prefab_component_storages[prefab_component_index]
ini_component = prefab_component_storage[prefab_place]
else
ini_component = fragment_default
end
end
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_component ~= nil and fragment_duplicate then
for place = b_place, e_place do
local new_component = fragment_duplicate(ini_component)
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
---@type evolved.default?, evolved.duplicate?
local req_fragment_default, req_fragment_duplicate =
__evolved_get(req_fragment, __DEFAULT, __DUPLICATE)
if req_fragment_duplicate then
for place = b_place, e_place do
local req_component = req_fragment_default
if req_component ~= nil then req_component = req_fragment_duplicate(req_component) end
if req_component == nil then req_component = true end
req_component_storage[place] = req_component
end
else
local req_component = req_fragment_default
if req_component == nil then req_component = true end
for place = b_place, e_place do
req_component_storage[place] = req_component
end
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
end
else
if ini_component == nil then
ini_component = true
end
for place = b_place, e_place do
component_storage[place] = ini_component
end
end
end
else
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
for component_index = 1, chunk_component_count do
local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
if component_index then
local component_storage = chunk_component_storages[component_index]
local ini_component = components[component_fragment]
local new_component = component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
local req_component = true
for place = b_place, e_place do
req_component_storage[place] = req_component
if ini_component == nil then
if chunk == prefab_chunk then
ini_component = component_storage[prefab_place]
else
local prefab_component_index = prefab_component_indices[component_fragment]
if prefab_component_index then
local prefab_component_storage = prefab_component_storages[prefab_component_index]
ini_component = prefab_component_storage[prefab_place]
else
ini_component = true
end
end
end
for place = b_place, e_place do
component_storage[place] = ini_component
end
end
end