Skip to content

Commit e09185e

Browse files
#1601 Implement ecs_shrink
1 parent de96203 commit e09185e

File tree

13 files changed

+629
-70
lines changed

13 files changed

+629
-70
lines changed

distr/flecs.c

Lines changed: 147 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ int32_t flecs_entity_index_not_alive_count(
163163
void flecs_entity_index_clear(
164164
ecs_entity_index_t *index);
165165

166+
/* Shrink entity index */
167+
void flecs_entity_index_shrink(
168+
ecs_entity_index_t *index);
169+
166170
/* Return number of alive entities in index */
167171
const uint64_t* flecs_entity_index_ids(
168172
const ecs_entity_index_t *index);
@@ -19760,6 +19764,28 @@ void flecs_component_ids_set(
1976019764
ecs_vec_get_t(&world->component_ids, ecs_entity_t, index)[0] = component;
1976119765
}
1976219766

19767+
void ecs_shrink(
19768+
ecs_world_t *world)
19769+
{
19770+
flecs_entity_index_shrink(&world->store.entity_index);
19771+
19772+
ecs_sparse_t *tables = &world->store.tables;
19773+
int32_t i, count = flecs_sparse_count(tables);
19774+
19775+
for (i = count - 1; i > 0; i --) {
19776+
ecs_table_t *table = flecs_sparse_get_dense_t(tables, ecs_table_t, i);
19777+
if (ecs_table_count(table)) {
19778+
flecs_table_shrink(world, table);
19779+
} else {
19780+
flecs_table_fini(world, table);
19781+
}
19782+
}
19783+
19784+
flecs_table_shrink(world, &world->store.root);
19785+
19786+
flecs_sparse_shrink(&world->store.tables);
19787+
}
19788+
1976319789
/**
1976419790
* @file addons/alerts.c
1976519791
* @brief Alerts addon.
@@ -29026,7 +29052,7 @@ void* flecs_brealloc_w_dbg_info(
2902629052
}
2902729053

2902829054
void* flecs_bdup(
29029-
ecs_block_allocator_t *ba,
29055+
ecs_block_allocator_t *ba,
2903029056
void *memory)
2903129057
{
2903229058
#ifdef FLECS_USE_OS_ALLOC
@@ -30144,33 +30170,33 @@ void flecs_name_index_ensure(
3014430170
/* Utility to get a pointer to the payload */
3014530171
#define DATA(array, size, offset) (ECS_OFFSET(array, size * offset))
3014630172

30147-
typedef struct ecs_page_t {
30173+
typedef struct ecs_sparse_page_t {
3014830174
int32_t *sparse; /* Sparse array with indices to dense array */
3014930175
void *data; /* Store data in sparse array to reduce
3015030176
* indirection and provide stable pointers. */
30151-
} ecs_page_t;
30177+
} ecs_sparse_page_t;
3015230178

3015330179
static
30154-
ecs_page_t* flecs_sparse_page_new(
30180+
ecs_sparse_page_t* flecs_sparse_page_new(
3015530181
ecs_sparse_t *sparse,
3015630182
int32_t page_index)
3015730183
{
3015830184
ecs_allocator_t *a = sparse->allocator;
3015930185
ecs_block_allocator_t *ca = sparse->page_allocator;
3016030186
int32_t count = ecs_vec_count(&sparse->pages);
30161-
ecs_page_t *pages;
30187+
ecs_sparse_page_t *pages;
3016230188

3016330189
if (count <= page_index) {
30164-
ecs_vec_set_count_t(a, &sparse->pages, ecs_page_t, page_index + 1);
30165-
pages = ecs_vec_first_t(&sparse->pages, ecs_page_t);
30166-
ecs_os_memset_n(&pages[count], 0, ecs_page_t, (1 + page_index - count));
30190+
ecs_vec_set_count_t(a, &sparse->pages, ecs_sparse_page_t, page_index + 1);
30191+
pages = ecs_vec_first_t(&sparse->pages, ecs_sparse_page_t);
30192+
ecs_os_memset_n(&pages[count], 0, ecs_sparse_page_t, (1 + page_index - count));
3016730193
} else {
30168-
pages = ecs_vec_first_t(&sparse->pages, ecs_page_t);
30194+
pages = ecs_vec_first_t(&sparse->pages, ecs_sparse_page_t);
3016930195
}
3017030196

3017130197
ecs_assert(pages != NULL, ECS_INTERNAL_ERROR, NULL);
3017230198

30173-
ecs_page_t *result = &pages[page_index];
30199+
ecs_sparse_page_t *result = &pages[page_index];
3017430200
ecs_assert(result->sparse == NULL, ECS_INTERNAL_ERROR, NULL);
3017530201
ecs_assert(result->data == NULL, ECS_INTERNAL_ERROR, NULL);
3017630202

@@ -30196,7 +30222,7 @@ ecs_page_t* flecs_sparse_page_new(
3019630222
static
3019730223
void flecs_sparse_page_free(
3019830224
ecs_sparse_t *sparse,
30199-
ecs_page_t *page)
30225+
ecs_sparse_page_t *page)
3020030226
{
3020130227
ecs_allocator_t *a = sparse->allocator;
3020230228
ecs_block_allocator_t *ca = sparse->page_allocator;
@@ -30214,24 +30240,25 @@ void flecs_sparse_page_free(
3021430240
}
3021530241

3021630242
static
30217-
ecs_page_t* flecs_sparse_get_page(
30243+
ecs_sparse_page_t* flecs_sparse_get_page(
3021830244
const ecs_sparse_t *sparse,
3021930245
int32_t page_index)
3022030246
{
3022130247
ecs_assert(page_index >= 0, ECS_INVALID_PARAMETER, NULL);
3022230248
if (page_index >= ecs_vec_count(&sparse->pages)) {
3022330249
return NULL;
3022430250
}
30225-
return ecs_vec_get_t(&sparse->pages, ecs_page_t, page_index);
30251+
return ecs_vec_get_t(&sparse->pages, ecs_sparse_page_t, page_index);
3022630252
}
3022730253

3022830254
static
30229-
ecs_page_t* flecs_sparse_get_or_create_page(
30255+
ecs_sparse_page_t* flecs_sparse_get_or_create_page(
3023030256
ecs_sparse_t *sparse,
3023130257
int32_t page_index)
3023230258
{
30233-
ecs_page_t *page = flecs_sparse_get_page(sparse, page_index);
30259+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, page_index);
3023430260
if (page && page->sparse) {
30261+
ecs_assert(page->data != NULL, ECS_INTERNAL_ERROR, NULL);
3023530262
return page;
3023630263
}
3023730264

@@ -30260,7 +30287,7 @@ uint64_t flecs_sparse_strip_generation(
3026030287

3026130288
static
3026230289
void flecs_sparse_assign_index(
30263-
ecs_page_t * page,
30290+
ecs_sparse_page_t * page,
3026430291
uint64_t * dense_array,
3026530292
uint64_t index,
3026630293
int32_t dense)
@@ -30318,7 +30345,7 @@ uint64_t flecs_sparse_create_id(
3031830345
uint64_t index = flecs_sparse_inc_id(sparse);
3031930346
flecs_sparse_grow_dense(sparse);
3032030347

30321-
ecs_page_t *page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index));
30348+
ecs_sparse_page_t *page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index));
3032230349
ecs_assert(page->sparse[FLECS_SPARSE_OFFSET(index)] == 0, ECS_INTERNAL_ERROR, NULL);
3032330350

3032430351
uint64_t *dense_array = ecs_vec_first_t(&sparse->dense, uint64_t);
@@ -30354,7 +30381,7 @@ void* flecs_sparse_get_sparse(
3035430381
uint64_t index)
3035530382
{
3035630383
flecs_sparse_strip_generation(&index);
30357-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30384+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3035830385
if (!page || !page->sparse) {
3035930386
return NULL;
3036030387
}
@@ -30372,15 +30399,15 @@ void* flecs_sparse_get_sparse(
3037230399
static
3037330400
void flecs_sparse_swap_dense(
3037430401
ecs_sparse_t * sparse,
30375-
ecs_page_t * page_a,
30402+
ecs_sparse_page_t * page_a,
3037630403
int32_t a,
3037730404
int32_t b)
3037830405
{
3037930406
uint64_t *dense_array = ecs_vec_first_t(&sparse->dense, uint64_t);
3038030407
uint64_t index_a = dense_array[a];
3038130408
uint64_t index_b = dense_array[b];
3038230409

30383-
ecs_page_t *page_b = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index_b));
30410+
ecs_sparse_page_t *page_b = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index_b));
3038430411
flecs_sparse_assign_index(page_a, dense_array, index_a, b);
3038530412
flecs_sparse_assign_index(page_b, dense_array, index_b, a);
3038630413
}
@@ -30397,7 +30424,7 @@ void flecs_sparse_init(
3039730424
result->allocator = allocator;
3039830425
result->page_allocator = page_allocator;
3039930426

30400-
ecs_vec_init_t(allocator, &result->pages, ecs_page_t, 0);
30427+
ecs_vec_init_t(allocator, &result->pages, ecs_sparse_page_t, 0);
3040130428
ecs_vec_init_t(allocator, &result->dense, uint64_t, 1);
3040230429
result->dense.count = 1;
3040330430

@@ -30414,7 +30441,7 @@ void flecs_sparse_clear(
3041430441
ecs_assert(sparse != NULL, ECS_INVALID_PARAMETER, NULL);
3041530442

3041630443
int32_t i, count = ecs_vec_count(&sparse->pages);
30417-
ecs_page_t *pages = ecs_vec_first_t(&sparse->pages, ecs_page_t);
30444+
ecs_sparse_page_t *pages = ecs_vec_first_t(&sparse->pages, ecs_sparse_page_t);
3041830445
for (i = 0; i < count; i ++) {
3041930446
int32_t *indices = pages[i].sparse;
3042030447
if (indices) {
@@ -30434,12 +30461,12 @@ void flecs_sparse_fini(
3043430461
ecs_assert(sparse != NULL, ECS_INTERNAL_ERROR, NULL);
3043530462

3043630463
int32_t i, count = ecs_vec_count(&sparse->pages);
30437-
ecs_page_t *pages = ecs_vec_first_t(&sparse->pages, ecs_page_t);
30464+
ecs_sparse_page_t *pages = ecs_vec_first_t(&sparse->pages, ecs_sparse_page_t);
3043830465
for (i = 0; i < count; i ++) {
3043930466
flecs_sparse_page_free(sparse, &pages[i]);
3044030467
}
3044130468

30442-
ecs_vec_fini_t(sparse->allocator, &sparse->pages, ecs_page_t);
30469+
ecs_vec_fini_t(sparse->allocator, &sparse->pages, ecs_sparse_page_t);
3044330470
ecs_vec_fini_t(sparse->allocator, &sparse->dense, uint64_t);
3044430471
}
3044530472

@@ -30457,8 +30484,9 @@ void* flecs_sparse_add(
3045730484
ecs_assert(sparse != NULL, ECS_INVALID_PARAMETER, NULL);
3045830485
ecs_assert(!size || size == sparse->size, ECS_INVALID_PARAMETER, NULL);
3045930486
uint64_t index = flecs_sparse_new_index(sparse);
30460-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30487+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3046130488
ecs_assert(page != NULL, ECS_INTERNAL_ERROR, NULL);
30489+
ecs_assert(page->data != NULL, ECS_INTERNAL_ERROR, NULL);
3046230490
return DATA(page->data, size, FLECS_SPARSE_OFFSET(index));
3046330491
}
3046430492

@@ -30481,7 +30509,7 @@ void* flecs_sparse_ensure(
3048130509
(void)size;
3048230510

3048330511
uint64_t gen = flecs_sparse_strip_generation(&index);
30484-
ecs_page_t *page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index));
30512+
ecs_sparse_page_t *page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index));
3048530513
int32_t offset = FLECS_SPARSE_OFFSET(index);
3048630514
int32_t dense = page->sparse[offset];
3048730515

@@ -30528,7 +30556,7 @@ void* flecs_sparse_ensure(
3052830556
/* If there are unused elements in the list, move the first unused
3052930557
* element to the end of the list */
3053030558
uint64_t unused = dense_array[count];
30531-
ecs_page_t *unused_page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(unused));
30559+
ecs_sparse_page_t *unused_page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(unused));
3053230560
flecs_sparse_assign_index(unused_page, dense_array, unused, dense_count);
3053330561
}
3053430562

@@ -30550,7 +30578,7 @@ void* flecs_sparse_ensure_fast(
3055030578
(void)size;
3055130579

3055230580
uint32_t index = (uint32_t)index_long;
30553-
ecs_page_t *page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index));
30581+
ecs_sparse_page_t *page = flecs_sparse_get_or_create_page(sparse, FLECS_SPARSE_PAGE(index));
3055430582
int32_t offset = FLECS_SPARSE_OFFSET(index);
3055530583
int32_t dense = page->sparse[offset];
3055630584
int32_t count = sparse->count;
@@ -30578,7 +30606,7 @@ void* flecs_sparse_remove_fast(
3057830606
ecs_assert(!size || size == sparse->size, ECS_INVALID_PARAMETER, NULL);
3057930607
(void)size;
3058030608

30581-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30609+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3058230610
if (!page || !page->sparse) {
3058330611
return NULL;
3058430612
}
@@ -30616,7 +30644,7 @@ void flecs_sparse_remove(
3061630644
ecs_assert(!size || size == sparse->size, ECS_INVALID_PARAMETER, NULL);
3061730645
(void)size;
3061830646

30619-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30647+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3062030648
if (!page || !page->sparse) {
3062130649
return;
3062230650
}
@@ -30680,7 +30708,7 @@ bool flecs_sparse_is_alive(
3068030708
const ecs_sparse_t *sparse,
3068130709
uint64_t index)
3068230710
{
30683-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30711+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3068430712
if (!page || !page->sparse) {
3068530713
return false;
3068630714
}
@@ -30711,7 +30739,7 @@ void* flecs_sparse_try(
3071130739
ecs_assert(sparse != NULL, ECS_INVALID_PARAMETER, NULL);
3071230740
ecs_assert(!size || size == sparse->size, ECS_INVALID_PARAMETER, NULL);
3071330741
(void)size;
30714-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30742+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3071530743
if (!page || !page->sparse) {
3071630744
return NULL;
3071730745
}
@@ -30742,7 +30770,7 @@ void* flecs_sparse_get(
3074230770
ecs_assert(!size || size == sparse->size, ECS_INVALID_PARAMETER, NULL);
3074330771
(void)size;
3074430772

30745-
ecs_page_t *page = ecs_vec_get_t(&sparse->pages, ecs_page_t, FLECS_SPARSE_PAGE(index));
30773+
ecs_sparse_page_t *page = ecs_vec_get_t(&sparse->pages, ecs_sparse_page_t, FLECS_SPARSE_PAGE(index));
3074630774
int32_t offset = FLECS_SPARSE_OFFSET(index);
3074730775
int32_t dense = page->sparse[offset];
3074830776
ecs_assert(dense != 0, ECS_INTERNAL_ERROR, NULL);
@@ -30768,7 +30796,7 @@ void* flecs_sparse_get_any(
3076830796
(void)size;
3076930797

3077030798
flecs_sparse_strip_generation(&index);
30771-
ecs_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
30799+
ecs_sparse_page_t *page = flecs_sparse_get_page(sparse, FLECS_SPARSE_PAGE(index));
3077230800
if (!page || !page->sparse) {
3077330801
return NULL;
3077430802
}
@@ -30805,6 +30833,43 @@ const uint64_t* flecs_sparse_ids(
3080530833
}
3080630834
}
3080730835

30836+
void flecs_sparse_shrink(
30837+
ecs_sparse_t *sparse)
30838+
{
30839+
int32_t i, e, max_page_index = 0, count = ecs_vec_count(&sparse->pages);
30840+
ecs_sparse_page_t *pages = ecs_vec_first_t(&sparse->pages,
30841+
ecs_sparse_page_t);
30842+
for (i = 0; i < count; i ++) {
30843+
ecs_sparse_page_t *page = &pages[i];
30844+
if (!page->sparse) {
30845+
ecs_assert(page->data == NULL, ECS_INTERNAL_ERROR, NULL);
30846+
continue;
30847+
}
30848+
30849+
bool has_alive = false;
30850+
for (e = 0; e < FLECS_SPARSE_PAGE_SIZE; e ++) {
30851+
uint64_t index =
30852+
flecs_ito(uint64_t, (i * FLECS_SPARSE_PAGE_SIZE) + e);
30853+
30854+
if (flecs_sparse_is_alive(sparse, index)) {
30855+
has_alive = true;
30856+
break;
30857+
}
30858+
}
30859+
30860+
if (!has_alive) {
30861+
flecs_sparse_page_free(sparse, page);
30862+
} else {
30863+
max_page_index = i;
30864+
}
30865+
}
30866+
30867+
ecs_vec_set_count_t(
30868+
sparse->allocator, &sparse->pages, ecs_sparse_page_t,
30869+
max_page_index + 1);
30870+
ecs_vec_reclaim_t(sparse->allocator, &sparse->pages, ecs_sparse_page_t);
30871+
}
30872+
3080830873
void ecs_sparse_init(
3080930874
ecs_sparse_t *sparse,
3081030875
ecs_size_t elem_size)
@@ -35705,6 +35770,54 @@ void flecs_entity_index_clear(
3570535770
index->max_id = 0;
3570635771
}
3570735772

35773+
void flecs_entity_index_shrink(
35774+
ecs_entity_index_t *index)
35775+
{
35776+
ecs_vec_set_count_t(
35777+
index->allocator, &index->dense, uint64_t, index->alive_count);
35778+
ecs_vec_reclaim_t(index->allocator, &index->dense, uint64_t);
35779+
35780+
int32_t i, e, max_page_index = 0, count = ecs_vec_count(&index->pages);
35781+
ecs_entity_index_page_t **pages = ecs_vec_first_t(&index->pages,
35782+
ecs_entity_index_page_t*);
35783+
for (i = 0; i < count; i ++) {
35784+
ecs_entity_index_page_t *page = pages[i];
35785+
if (!page) {
35786+
continue;
35787+
}
35788+
35789+
bool has_alive = false;
35790+
for (e = 0; e < FLECS_ENTITY_PAGE_SIZE; e ++) {
35791+
ecs_record_t *r = &page->records[e];
35792+
ecs_entity_t entity = flecs_ito(uint64_t, (i * 4096) + e);
35793+
35794+
if (r->dense) {
35795+
ecs_assert(flecs_entity_index_get_any(index, entity) == r,
35796+
ECS_INTERNAL_ERROR, NULL);
35797+
35798+
if (flecs_entity_index_is_alive(index, entity)) {
35799+
ecs_assert(flecs_entity_index_is_alive(index, entity),
35800+
ECS_INTERNAL_ERROR, NULL);
35801+
has_alive = true;
35802+
break;
35803+
}
35804+
}
35805+
}
35806+
35807+
if (!has_alive) {
35808+
flecs_bfree(&index->page_allocator, page);
35809+
pages[i] = NULL;
35810+
} else {
35811+
max_page_index = i;
35812+
}
35813+
}
35814+
35815+
ecs_vec_set_count_t(
35816+
index->allocator, &index->pages, ecs_entity_index_page_t*,
35817+
max_page_index + 1);
35818+
ecs_vec_reclaim_t(index->allocator, &index->pages, ecs_entity_index_page_t*);
35819+
}
35820+
3570835821
const uint64_t* flecs_entity_index_ids(
3570935822
const ecs_entity_index_t *index)
3571035823
{

0 commit comments

Comments
 (0)