diff --git a/dub.json b/dub.json index d5e4a87..52988fd 100755 --- a/dub.json +++ b/dub.json @@ -8,8 +8,7 @@ "license": "BSD", "sourcePaths" : ["source\/"], "dflags-posix-ldc": [ - "-defaultlib=phobos2-ldc,druntime-ldc", - "-fsanitize=address" + "-defaultlib=phobos2-ldc,druntime-ldc" ], "dflagss": [ "-betterC" diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 0a7017d..140d8f2 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -1403,7 +1403,9 @@ export class EntityManager ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length)))[0 .. info.components.length]; - uint j = 0; + EntityInfo* new_info = info; + + /*uint j = 0; uint k = 0; foreach (id; info.components) { @@ -1416,15 +1418,23 @@ export class EntityManager else if (del_ids[k] == info.components[j]) { k++; + new_info = new_info.getNewInfoAdd(del_ids[k]); } else ids[j++] = id; } 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); @@ -1513,8 +1523,8 @@ export class EntityManager return; EntitiesBlock* block = getMetaData(entity); EntityInfo* info = block.type_info; - ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 - .. info.components.length + num]; + /*ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 + .. info.components.length + num];*/ /*ushort[num] new_ids; 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 len = 0; //foreach (ref id; ids) @@ -1569,6 +1581,7 @@ export class EntityManager else if (j >= info.components.length) { *id = new_ids[k++]; + new_info = new_info.getNewInfoAdd(*id); //continue; } else if (new_ids[k] == info.components[j]) @@ -1577,18 +1590,26 @@ export class EntityManager k++; } /*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]) { *id = new_ids[k++]; + new_info = new_info.getNewInfoAdd(*id); } else *id = info.components[j++]; } 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); @@ -1598,8 +1619,8 @@ export class EntityManager new_entity.id = entity.id; new_entity.updateID(); - j = 0; - k = 0; + uint j = 0; + uint k = 0; static if (EntityID.sizeof == 8) uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3); 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] + ( 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() { if(components)Mallocator.instance.dispose(components); @@ -2435,6 +2532,11 @@ export class EntityManager ///deltas in memory for components in EntityTemplate 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 ushort alignment; //unused in linear-layout ///size of entity (with alignment respect) diff --git a/tests/tests.d b/tests/tests.d index 03fcc97..edd8b16 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -600,13 +600,25 @@ int main() foreach (i; 0 .. 1_000_000) { EntityManager.instance.addComponents(entities[i],TestComp5()); - //if((i & 0x00FFFF) == 0)gEM.commit(); + if((i & 0x00FFFF) == 0)gEM.commit(); } gEM.commit(); dur = (MonoTime.currTime - time).total!"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); time = MonoTime.currTime;