mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2026-03-22 04:44:06 +07:00
chunk purging with pairs
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
- Add multi-spawn to the builder to spawn multiple entities at once.
|
||||
- Add a function to shrink storages to free unused memory.
|
||||
- Should we cache the result of without_unique_fragments to clone faster?
|
||||
- Mark all internal fragments with a some special tag
|
||||
- observers and events
|
||||
- add INDEX fragment trait
|
||||
- use compact prefix-tree for chunks
|
||||
|
||||
@@ -6,20 +6,20 @@ require 'develop.testing.pairs_tests'
|
||||
require 'develop.testing.requires_fragment_tests'
|
||||
require 'develop.testing.system_as_query_tests'
|
||||
|
||||
-- require 'develop.unbench'
|
||||
-- require 'develop.usbench'
|
||||
require 'develop.unbench'
|
||||
require 'develop.usbench'
|
||||
|
||||
-- local basics = require 'develop.basics'
|
||||
local basics = require 'develop.basics'
|
||||
|
||||
-- print '----------------------------------------'
|
||||
-- basics.describe_fuzz 'develop.fuzzing.destroy_fuzz'
|
||||
-- print '----------------------------------------'
|
||||
-- basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz'
|
||||
-- print '----------------------------------------'
|
||||
-- basics.describe_fuzz 'develop.fuzzing.explicit_fuzz'
|
||||
-- print '----------------------------------------'
|
||||
-- basics.describe_fuzz 'develop.fuzzing.pack_unpack_fuzz'
|
||||
-- print '----------------------------------------'
|
||||
-- basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
|
||||
-- print '----------------------------------------'
|
||||
-- basics.describe_fuzz 'develop.fuzzing.unique_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.destroy_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.explicit_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.pack_unpack_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.unique_fuzz'
|
||||
|
||||
@@ -1102,10 +1102,77 @@ do
|
||||
assert(evo.get(e, evo.pair(p, s)) == 42)
|
||||
end
|
||||
|
||||
do
|
||||
evo.collect_garbage()
|
||||
|
||||
local f, p1, s1, p2, s2 = evo.id(5)
|
||||
|
||||
local e1 = evo.builder()
|
||||
:set(f, 21)
|
||||
:set(evo.pair(p1, s1), 42)
|
||||
:set(evo.pair(p2, s2), 84)
|
||||
:spawn()
|
||||
|
||||
local e2 = evo.builder()
|
||||
:set(f, 21)
|
||||
:set(evo.pair(p1, s1), 42)
|
||||
:set(evo.pair(p2, s2), 84)
|
||||
:spawn()
|
||||
|
||||
local f_chunk = evo.chunk(f)
|
||||
local f_p2s2_chunk = evo.chunk(f, evo.pair(p2, s2))
|
||||
local f_p1s1_p2s2_chunk = evo.chunk(f, evo.pair(p1, s1), evo.pair(p2, s2))
|
||||
|
||||
assert(f_p1s1_p2s2_chunk:entities()[1] == e1)
|
||||
assert(f_p1s1_p2s2_chunk:entities()[2] == e2)
|
||||
|
||||
evo.remove(e1, evo.pair(p1, evo.ANY))
|
||||
|
||||
assert(f_p2s2_chunk:entities()[1] == e1)
|
||||
assert(f_p1s1_p2s2_chunk:entities()[1] == e2)
|
||||
|
||||
evo.remove(e1, evo.pair(p2, evo.ANY))
|
||||
|
||||
assert(f_chunk:entities()[1] == e1)
|
||||
assert(f_p1s1_p2s2_chunk:entities()[1] == e2)
|
||||
|
||||
evo.collect_garbage()
|
||||
|
||||
assert(f_chunk:alive())
|
||||
assert(not f_p2s2_chunk:alive())
|
||||
assert(f_p1s1_p2s2_chunk:alive())
|
||||
|
||||
evo.remove(e2, evo.pair(p1, evo.ANY))
|
||||
|
||||
local new_f_p2s2_chunk = evo.chunk(f, evo.pair(p2, s2))
|
||||
assert(new_f_p2s2_chunk:entities()[1] == e2)
|
||||
end
|
||||
|
||||
do
|
||||
evo.collect_garbage()
|
||||
|
||||
local f, p1, p2, s1, s2 = evo.id(5)
|
||||
|
||||
local e1 = evo.builder()
|
||||
:set(f, 21)
|
||||
:set(evo.pair(p1, s1), 42)
|
||||
:set(evo.pair(p2, s2), 84)
|
||||
:spawn()
|
||||
|
||||
local f_p1s1_p2s2_chunk = evo.chunk(f, evo.pair(p1, s1), evo.pair(p2, s2))
|
||||
assert(f_p1s1_p2s2_chunk:entities()[1] == e1)
|
||||
|
||||
evo.destroy(p2, s2)
|
||||
|
||||
evo.collect_garbage()
|
||||
|
||||
local f_p1s1_chunk = evo.chunk(f, evo.pair(p1, s1))
|
||||
assert(f_p1s1_chunk:entities()[1] == e1)
|
||||
end
|
||||
|
||||
-- TODO:
|
||||
-- How should required fragments work with pairs?
|
||||
-- How can we set defaults for paired fragments?
|
||||
-- Prevent setting wildcard pairs to entities!
|
||||
-- Should we have destruction policies analog for pairs?
|
||||
-- Do not forget to purge chunks with pairs!
|
||||
-- Should we call hooks for pairs?
|
||||
|
||||
114
evolved.lua
114
evolved.lua
@@ -627,10 +627,14 @@ end
|
||||
---@param src_item_first integer
|
||||
---@param src_item_last integer
|
||||
---@param dst_al evolved.assoc_list<K>
|
||||
---@return integer new_dst_item_count
|
||||
function __assoc_list_move(src_item_list, src_item_first, src_item_last, dst_al)
|
||||
dst_al.__item_count = __assoc_list_move_ex(
|
||||
local new_dst_item_count = __assoc_list_move_ex(
|
||||
src_item_list, src_item_first, src_item_last,
|
||||
dst_al.__item_set, dst_al.__item_list, dst_al.__item_count)
|
||||
|
||||
dst_al.__item_count = new_dst_item_count
|
||||
return new_dst_item_count
|
||||
end
|
||||
|
||||
---@generic K
|
||||
@@ -690,10 +694,14 @@ end
|
||||
---@generic K
|
||||
---@param al evolved.assoc_list<K>
|
||||
---@param item K
|
||||
---@return integer new_al_count
|
||||
function __assoc_list_insert(al, item)
|
||||
al.__item_count = __assoc_list_insert_ex(
|
||||
local new_al_count = __assoc_list_insert_ex(
|
||||
al.__item_set, al.__item_list, al.__item_count,
|
||||
item)
|
||||
|
||||
al.__item_count = new_al_count
|
||||
return new_al_count
|
||||
end
|
||||
|
||||
---@generic K
|
||||
@@ -720,10 +728,14 @@ end
|
||||
---@generic K
|
||||
---@param al evolved.assoc_list<K>
|
||||
---@param item K
|
||||
---@return integer new_al_count
|
||||
function __assoc_list_remove(al, item)
|
||||
al.__item_count = __assoc_list_remove_ex(
|
||||
local new_al_count = __assoc_list_remove_ex(
|
||||
al.__item_set, al.__item_list, al.__item_count,
|
||||
item)
|
||||
|
||||
al.__item_count = new_al_count
|
||||
return new_al_count
|
||||
end
|
||||
|
||||
---@generic K
|
||||
@@ -1744,7 +1756,12 @@ local function __chunk_without_fragment(chunk, fragment)
|
||||
return chunk
|
||||
end
|
||||
|
||||
local sib_chunk = chunk
|
||||
if not chunk.__secondary_pairs[secondary] then
|
||||
-- the chunk does not have such pairs
|
||||
return chunk
|
||||
end
|
||||
|
||||
local sib_chunk = chunk.__parent
|
||||
|
||||
while sib_chunk and sib_chunk.__has_pair_fragments and sib_chunk.__secondary_pairs[secondary] do
|
||||
sib_chunk = sib_chunk.__parent
|
||||
@@ -1777,7 +1794,12 @@ local function __chunk_without_fragment(chunk, fragment)
|
||||
return chunk
|
||||
end
|
||||
|
||||
local sib_chunk = chunk
|
||||
if not chunk.__primary_pairs[primary] then
|
||||
-- the chunk does not have such pairs
|
||||
return chunk
|
||||
end
|
||||
|
||||
local sib_chunk = chunk.__parent
|
||||
|
||||
while sib_chunk and sib_chunk.__has_pair_fragments and sib_chunk.__primary_pairs[primary] do
|
||||
sib_chunk = sib_chunk.__parent
|
||||
@@ -2878,8 +2900,8 @@ local function __purge_chunk(chunk)
|
||||
local chunk_parent = chunk.__parent
|
||||
local chunk_fragment = chunk.__fragment
|
||||
|
||||
local major_chunks = __major_chunks[chunk_fragment]
|
||||
local minor_chunks = __minor_chunks[chunk_fragment]
|
||||
local chunk_fragment_list = chunk.__fragment_list
|
||||
local chunk_fragment_count = chunk.__fragment_count
|
||||
|
||||
local with_fragment_edges = chunk.__with_fragment_edges
|
||||
local without_fragment_edges = chunk.__without_fragment_edges
|
||||
@@ -2888,19 +2910,37 @@ local function __purge_chunk(chunk)
|
||||
__root_chunks[chunk_fragment] = nil
|
||||
end
|
||||
|
||||
if major_chunks then
|
||||
__assoc_list_remove(major_chunks, chunk)
|
||||
do
|
||||
local major_fragment = chunk_fragment
|
||||
local major_chunks = __major_chunks[major_fragment]
|
||||
|
||||
if major_chunks.__item_count == 0 then
|
||||
__major_chunks[chunk_fragment] = nil
|
||||
if major_chunks and __assoc_list_remove(major_chunks, chunk) == 0 then
|
||||
__major_chunks[major_fragment] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if minor_chunks then
|
||||
__assoc_list_remove(minor_chunks, chunk)
|
||||
for i = 1, chunk_fragment_count do
|
||||
local minor_fragment = chunk_fragment_list[i]
|
||||
local minor_chunks = __minor_chunks[minor_fragment]
|
||||
|
||||
if minor_chunks.__item_count == 0 then
|
||||
__minor_chunks[chunk_fragment] = nil
|
||||
if minor_chunks and __assoc_list_remove(minor_chunks, chunk) == 0 then
|
||||
__minor_chunks[minor_fragment] = nil
|
||||
end
|
||||
end
|
||||
|
||||
for primary_fragment in __lua_next, chunk.__primary_pairs do
|
||||
local primary_chunks = __primary_chunks[primary_fragment]
|
||||
|
||||
if primary_chunks and __assoc_list_remove(primary_chunks, chunk) == 0 then
|
||||
__primary_chunks[primary_fragment] = nil
|
||||
end
|
||||
end
|
||||
|
||||
for secondary_fragment in __lua_next, chunk.__secondary_pairs do
|
||||
local secondary_chunks = __secondary_chunks[secondary_fragment]
|
||||
|
||||
if secondary_chunks and __assoc_list_remove(secondary_chunks, chunk) == 0 then
|
||||
__secondary_chunks[secondary_fragment] = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3129,15 +3169,15 @@ function __chunk_set(old_chunk, fragment, component)
|
||||
local old_entity_list = old_chunk.__entity_list
|
||||
local old_entity_count = old_chunk.__entity_count
|
||||
|
||||
if old_entity_count == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local old_component_count = old_chunk.__component_count
|
||||
local old_component_indices = old_chunk.__component_indices
|
||||
local old_component_storages = old_chunk.__component_storages
|
||||
local old_component_fragments = old_chunk.__component_fragments
|
||||
|
||||
if old_entity_count == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if __is_wildcard(fragment) then
|
||||
local primary, secondary = __evolved_unpair(fragment)
|
||||
|
||||
@@ -3569,24 +3609,24 @@ function __chunk_remove(old_chunk, ...)
|
||||
return
|
||||
end
|
||||
|
||||
local new_chunk = __chunk_without_fragments(old_chunk, ...)
|
||||
|
||||
if old_chunk == new_chunk then
|
||||
return
|
||||
end
|
||||
|
||||
local old_entity_list = old_chunk.__entity_list
|
||||
local old_entity_count = old_chunk.__entity_count
|
||||
|
||||
if old_entity_count == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local old_fragment_list = old_chunk.__fragment_list
|
||||
local old_fragment_count = old_chunk.__fragment_count
|
||||
local old_component_indices = old_chunk.__component_indices
|
||||
local old_component_storages = old_chunk.__component_storages
|
||||
|
||||
if old_entity_count == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local new_chunk = __chunk_without_fragments(old_chunk, ...)
|
||||
|
||||
if old_chunk == new_chunk then
|
||||
return
|
||||
end
|
||||
|
||||
if old_chunk.__has_remove_hooks then
|
||||
---@type table<evolved.fragment, integer>
|
||||
local new_fragment_set = new_chunk and new_chunk.__fragment_set
|
||||
@@ -6929,12 +6969,8 @@ __evolved_set(__GROUP, __ON_SET, function(system, _, new_group, old_group)
|
||||
if old_group then
|
||||
local old_group_systems = __group_subsystems[old_group]
|
||||
|
||||
if old_group_systems then
|
||||
__assoc_list_remove(old_group_systems, system)
|
||||
|
||||
if old_group_systems.__item_count == 0 then
|
||||
__group_subsystems[old_group] = nil
|
||||
end
|
||||
if old_group_systems and __assoc_list_remove(old_group_systems, system) == 0 then
|
||||
__group_subsystems[old_group] = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6953,12 +6989,8 @@ end)
|
||||
__evolved_set(__GROUP, __ON_REMOVE, function(system, _, old_group)
|
||||
local old_group_systems = __group_subsystems[old_group]
|
||||
|
||||
if old_group_systems then
|
||||
__assoc_list_remove(old_group_systems, system)
|
||||
|
||||
if old_group_systems.__item_count == 0 then
|
||||
__group_subsystems[old_group] = nil
|
||||
end
|
||||
if old_group_systems and __assoc_list_remove(old_group_systems, system) == 0 then
|
||||
__group_subsystems[old_group] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user