-added components change caching (no HashMap searching during components adding or removing)

This commit is contained in:
Mergul 2019-06-18 17:49:51 +02:00
parent 235bbb49f2
commit b04ab77e0c
3 changed files with 128 additions and 15 deletions

View file

@ -8,8 +8,7 @@
"license": "BSD", "license": "BSD",
"sourcePaths" : ["source\/"], "sourcePaths" : ["source\/"],
"dflags-posix-ldc": [ "dflags-posix-ldc": [
"-defaultlib=phobos2-ldc,druntime-ldc", "-defaultlib=phobos2-ldc,druntime-ldc"
"-fsanitize=address"
], ],
"dflagss": [ "dflagss": [
"-betterC" "-betterC"

View file

@ -1403,7 +1403,9 @@ export class EntityManager
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length)))[0 ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length)))[0
.. info.components.length]; .. info.components.length];
uint j = 0; EntityInfo* new_info = info;
/*uint j = 0;
uint k = 0; uint k = 0;
foreach (id; info.components) foreach (id; info.components)
{ {
@ -1416,15 +1418,23 @@ export class EntityManager
else if (del_ids[k] == info.components[j]) else if (del_ids[k] == info.components[j])
{ {
k++; k++;
new_info = new_info.getNewInfoAdd(del_ids[k]);
} }
else else
ids[j++] = id; ids[j++] = id;
} }
if (j == info.components.length) if (j == info.components.length)
return; return;*/
EntityInfo* new_info = getEntityInfo(ids[0 .. j]); foreach(id;del_ids)
{
new_info = new_info.getNewInfoRemove(id);
}
if(new_info == info)return;
//EntityInfo* new_info = getEntityInfo(ids[0 .. j]);
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info); EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
@ -1513,8 +1523,8 @@ export class EntityManager
return; return;
EntitiesBlock* block = getMetaData(entity); EntitiesBlock* block = getMetaData(entity);
EntityInfo* info = block.type_info; EntityInfo* info = block.type_info;
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 /*ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
.. info.components.length + num]; .. info.components.length + num];*/
/*ushort[num] new_ids; /*ushort[num] new_ids;
static foreach (i, comp; Components) static foreach (i, comp; Components)
@ -1552,7 +1562,9 @@ export class EntityManager
} }
} }
uint j = 0; EntityInfo* new_info = info;
/* uint j = 0;
uint k = 0; uint k = 0;
uint len = 0; uint len = 0;
//foreach (ref id; ids) //foreach (ref id; ids)
@ -1569,6 +1581,7 @@ export class EntityManager
else if (j >= info.components.length) else if (j >= info.components.length)
{ {
*id = new_ids[k++]; *id = new_ids[k++];
new_info = new_info.getNewInfoAdd(*id);
//continue; //continue;
} }
else if (new_ids[k] == info.components[j]) else if (new_ids[k] == info.components[j])
@ -1577,18 +1590,26 @@ export class EntityManager
k++; k++;
} }
/*debug if (new_ids[k] == info.components[j]) /*debug if (new_ids[k] == info.components[j])
assert(0, "Trying to add already existing component!");*/ assert(0, "Trying to add already existing component!");//*
else if (new_ids[k] < info.components[j]) else if (new_ids[k] < info.components[j])
{ {
*id = new_ids[k++]; *id = new_ids[k++];
new_info = new_info.getNewInfoAdd(*id);
} }
else else
*id = info.components[j++]; *id = info.components[j++];
} }
if (len == info.components.length) if (len == info.components.length)
return; return;*/
EntityInfo* new_info = getEntityInfo(ids[0 .. len]); foreach(id;new_ids)
{
new_info = new_info.getNewInfoAdd(id);
}
if(new_info == info)return;
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info); EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
@ -1598,8 +1619,8 @@ export class EntityManager
new_entity.id = entity.id; new_entity.id = entity.id;
new_entity.updateID(); new_entity.updateID();
j = 0; uint j = 0;
k = 0; uint k = 0;
static if (EntityID.sizeof == 8) static if (EntityID.sizeof == 8)
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3); uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3);
else else
@ -1616,7 +1637,7 @@ export class EntityManager
} }
} }
foreach (ref id; ids[0 .. len]) foreach (ref id; new_info.components)//ids[0 .. len])
{ {
void* dst = cast(void*) new_block + new_info.deltas[id] + ( void* dst = cast(void*) new_block + new_info.deltas[id] + (
new_block.entities_count /*+ new_block.added_count*/ ) * components[id].size; new_block.entities_count /*+ new_block.added_count*/ ) * components[id].size;
@ -2416,6 +2437,82 @@ export class EntityManager
} }
} }
EntityInfo* getNewInfoAdd(ushort id)
{
if(comp_add_info.length < id)
{
EntityInfo*[] new_infos = Mallocator.instance.makeArray!(EntityInfo*)(instance.components.length);
if(comp_add_info !is null)
{
new_infos[0 .. comp_add_info.length] = comp_add_info[0 .. $];
Mallocator.instance.dispose(comp_add_info);
}
comp_add_info = new_infos;
}
if(comp_add_info[id])return comp_add_info[id];
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length + 1)))[0
.. components.length + 1];
uint len = 0;
foreach(comp; components)
{
if(id > comp)
{
ids[len++] = comp;
}
else if(id == comp)return &this;
else
{
ids[len++] = id;
ids[len++] = comp;
}
}
if(id > components[$ - 1])ids[len++] = id;
assert(len == components.length + 1);
EntityInfo* new_info = instance.getEntityInfo(ids[0 .. len]);
comp_add_info[id] = new_info;
return new_info;
}
EntityInfo* getNewInfoRemove(ushort id)
{
if(comp_rem_info.length < id)
{
EntityInfo*[] new_infos = Mallocator.instance.makeArray!(EntityInfo*)(instance.components.length);
if(comp_rem_info !is null)
{
new_infos[0 .. comp_rem_info.length] = comp_rem_info[0 .. $];
Mallocator.instance.dispose(comp_rem_info);
}
comp_rem_info = new_infos;
}
if(comp_rem_info[id])return comp_rem_info[id];
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length - 1)))[0
.. components.length - 1];
uint len = 0;
foreach(comp; components)
{
if(id != comp)
{
ids[len++] = comp;
}
}
if(len == components.length)return &this;
assert(len == components.length - 1);
EntityInfo* new_info = instance.getEntityInfo(ids[0 .. len]);
comp_rem_info[id] = new_info;
return new_info;
}
~this() ~this()
{ {
if(components)Mallocator.instance.dispose(components); if(components)Mallocator.instance.dispose(components);
@ -2435,6 +2532,11 @@ export class EntityManager
///deltas in memory for components in EntityTemplate ///deltas in memory for components in EntityTemplate
ushort[] tmpl_deltas; ushort[] tmpl_deltas;
///cached new infos after adding component
EntityInfo*[] comp_add_info;
///cached new infos after removing component
EntityInfo*[] comp_rem_info;
///alignment of whole entity ///alignment of whole entity
ushort alignment; //unused in linear-layout ushort alignment; //unused in linear-layout
///size of entity (with alignment respect) ///size of entity (with alignment respect)

View file

@ -600,13 +600,25 @@ int main()
foreach (i; 0 .. 1_000_000) foreach (i; 0 .. 1_000_000)
{ {
EntityManager.instance.addComponents(entities[i],TestComp5()); EntityManager.instance.addComponents(entities[i],TestComp5());
//if((i & 0x00FFFF) == 0)gEM.commit(); if((i & 0x00FFFF) == 0)gEM.commit();
} }
gEM.commit(); gEM.commit();
dur = (MonoTime.currTime - time).total!"usecs"; dur = (MonoTime.currTime - time).total!"usecs";
writeln("Components adding: ", dur, " usecs"); writeln("Components adding: ", dur, " usecs");
time = MonoTime.currTime;
foreach (i; 0 .. 1_000_000)
{
EntityManager.instance.removeComponents!TestComp5(entities[i]);
//if((i & 0x00FFFF) == 0)gEM.commit();
}
gEM.commit();
dur = (MonoTime.currTime - time).total!"usecs";
writeln("Components removing: ", dur, " usecs");
Mallocator.instance.dispose(entities); Mallocator.instance.dispose(entities);
time = MonoTime.currTime; time = MonoTime.currTime;