fix batch optimizations with reallocs

This commit is contained in:
BlackMATov
2026-01-13 04:47:16 +07:00
parent e75ddef396
commit c52f708184
2 changed files with 168 additions and 27 deletions
+100
View File
@@ -19,10 +19,18 @@ local DOUBLE_TYPEOF = ffi.typeof('double')
local DOUBLE_SIZEOF = ffi.sizeof(DOUBLE_TYPEOF)
local DOUBLE_STORAGE_TYPEOF = ffi.typeof('$[?]', DOUBLE_TYPEOF)
local STORAGE_SIZES = {}
---@type evolved.realloc
local function float_realloc(old_storage, old_size, new_size)
if old_storage then
assert(STORAGE_SIZES[old_storage] == old_size)
end
local new_storage = ffi.new(FLOAT_STORAGE_TYPEOF, new_size + 1)
STORAGE_SIZES[new_storage] = new_size
if old_storage then
ffi.copy(new_storage + 1, old_storage + 1, math.min(old_size, new_size) * FLOAT_SIZEOF)
end
@@ -32,8 +40,14 @@ end
---@type evolved.realloc
local function double_realloc(old_storage, old_size, new_size)
if old_storage then
assert(STORAGE_SIZES[old_storage] == old_size)
end
local new_storage = ffi.new(DOUBLE_STORAGE_TYPEOF, new_size + 1)
STORAGE_SIZES[new_storage] = new_size
if old_storage then
ffi.copy(new_storage + 1, old_storage + 1, math.min(old_size, new_size) * DOUBLE_SIZEOF)
end
@@ -299,3 +313,89 @@ do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
end
end
do
evo.collect_garbage()
local f1 = evo.builder():name('f1'):realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():name('f2'):realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es, ec = evo.multi_spawn(40, { [f2] = 2 })
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q2)
end
do
local es, ec = evo.multi_spawn(50, { [f1] = 1, [f2] = 2 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_remove(q1, f1)
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q1, q2)
end
do
evo.spawn({ [f1] = 1 })
evo.spawn({ [f2] = 2 })
evo.spawn({ [f1] = 1, [f2] = 2 })
end
evo.collect_garbage()
end
do
evo.collect_garbage()
local f1 = evo.builder():name('f1'):realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():name('f2'):realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es, ec = evo.multi_spawn(40, { [f1] = 1, [f2] = 2 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q2)
end
do
local es, ec = evo.multi_spawn(50, { [f1] = 1 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(not evo.has(es[i], f2))
end
evo.batch_set(q1, f2, 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q1, q2)
end
do
evo.spawn({ [f1] = 1 })
evo.spawn({ [f2] = 2 })
evo.spawn({ [f1] = 1, [f2] = 2 })
end
evo.collect_garbage()
end
+68 -27
View File
@@ -2900,10 +2900,6 @@ function __expand_chunk(chunk, min_capacity)
__error_fmt('this operation should be deferred')
end
if min_capacity < 4 then
min_capacity = 4
end
local entity_count = chunk.__entity_count
if min_capacity < entity_count then
@@ -2922,6 +2918,10 @@ function __expand_chunk(chunk, min_capacity)
new_capacity = min_capacity
end
if new_capacity < 4 then
new_capacity = 4
end
if chunk.__has_storage_reallocs then
local component_count = chunk.__component_count
local component_storages = chunk.__component_storages
@@ -2945,13 +2945,12 @@ function __expand_chunk(chunk, min_capacity)
end
---@param chunk evolved.chunk
function __shrink_chunk(chunk)
---@param min_capacity integer
function __shrink_chunk(chunk, min_capacity)
if __defer_depth <= 0 then
__error_fmt('this operation should be deferred')
end
local min_capacity = 4
local entity_count = chunk.__entity_count
if min_capacity < entity_count then
@@ -3349,10 +3348,28 @@ function __chunk_set(old_chunk, fragment, component)
for old_ci = 1, old_component_count do
local old_f = old_component_fragments[old_ci]
local new_ci = new_component_indices[old_f]
old_component_storages[old_ci], new_component_storages[new_ci] =
new_component_storages[new_ci], old_component_storages[old_ci]
local new_ci = new_component_indices[old_f]
local new_cr = new_component_reallocs[new_ci]
if new_cr then
local old_cs = old_component_storages[old_ci]
local new_cs = new_component_storages[new_ci]
local new_cm = new_component_compmoves[new_ci]
if new_cm then
new_cm(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
else
for old_place = 1, old_entity_count do
local new_place = new_entity_count + old_place
new_cs[new_place] = old_cs[old_place]
end
end
else
old_component_storages[old_ci], new_component_storages[new_ci] =
new_component_storages[new_ci], old_component_storages[old_ci]
end
end
new_chunk.__entity_count = sum_entity_count
@@ -3364,14 +3381,17 @@ function __chunk_set(old_chunk, fragment, component)
local new_ci = new_component_indices[old_f]
local new_cs = new_component_storages[new_ci]
local new_cr = new_component_reallocs[new_ci]
local new_cm = new_component_compmoves[new_ci]
if new_cm then
new_cm(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
elseif new_cr then
for old_place = 1, old_entity_count do
local new_place = new_entity_count + old_place
new_cs[new_place] = old_cs[old_place]
if new_cr then
local new_cm = new_component_compmoves[new_ci]
if new_cm then
new_cm(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
else
for old_place = 1, old_entity_count do
local new_place = new_entity_count + old_place
new_cs[new_place] = old_cs[old_place]
end
end
else
__lua_table_move(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
@@ -3677,10 +3697,28 @@ function __chunk_remove(old_chunk, ...)
for new_ci = 1, new_component_count do
local new_f = new_component_fragments[new_ci]
local new_cr = new_component_reallocs[new_ci]
local old_ci = old_component_indices[new_f]
old_component_storages[old_ci], new_component_storages[new_ci] =
new_component_storages[new_ci], old_component_storages[old_ci]
if new_cr then
local new_cs = new_component_storages[new_ci]
local new_cm = new_component_compmoves[new_ci]
local old_cs = old_component_storages[old_ci]
if new_cm then
new_cm(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
else
for old_place = 1, old_entity_count do
local new_place = new_entity_count + old_place
new_cs[new_place] = old_cs[old_place]
end
end
else
old_component_storages[old_ci], new_component_storages[new_ci] =
new_component_storages[new_ci], old_component_storages[old_ci]
end
end
new_chunk.__entity_count = sum_entity_count
@@ -3689,17 +3727,20 @@ function __chunk_remove(old_chunk, ...)
local new_f = new_component_fragments[new_ci]
local new_cs = new_component_storages[new_ci]
local new_cr = new_component_reallocs[new_ci]
local new_cm = new_component_compmoves[new_ci]
local old_ci = old_component_indices[new_f]
local old_cs = old_component_storages[old_ci]
if new_cm then
new_cm(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
elseif new_cr then
for old_place = 1, old_entity_count do
local new_place = new_entity_count + old_place
new_cs[new_place] = old_cs[old_place]
if new_cr then
local new_cm = new_component_compmoves[new_ci]
if new_cm then
new_cm(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
else
for old_place = 1, old_entity_count do
local new_place = new_entity_count + old_place
new_cs[new_place] = old_cs[old_place]
end
end
else
__lua_table_move(old_cs, 1, old_entity_count, new_entity_count + 1, new_cs)
@@ -5669,7 +5710,7 @@ function __evolved_collect_garbage()
if should_be_purged then
__purge_chunk(postorder_chunk)
else
__shrink_chunk(postorder_chunk)
__shrink_chunk(postorder_chunk, 0)
end
end