remove bitarray allocations on query

pull/5/head
Evan Hemsley 2019-12-22 11:54:37 -08:00
parent 120fb738d7
commit 5299d6ddad
1 changed files with 40 additions and 21 deletions

View File

@ -14,6 +14,16 @@ namespace Encompass
private Dictionary<Type, int> typeToIndex; private Dictionary<Type, int> typeToIndex;
public ComponentStore UpToDateComponentStore { get; private set; } public ComponentStore UpToDateComponentStore { get; private set; }
// bitarray references to avoid garbage collection
BitArray pendingMask;
BitArray readMask;
BitArray withMask;
BitArray withoutMask;
BitArray notWithMask;
BitArray solverArrayA;
BitArray solverArrayB;
BitArray solverArrayC;
public ComponentUpdateManager(Dictionary<Type, int> typeToIndex) public ComponentUpdateManager(Dictionary<Type, int> typeToIndex)
{ {
existingAndPendingComponentStore = new ComponentStore(typeToIndex); existingAndPendingComponentStore = new ComponentStore(typeToIndex);
@ -37,6 +47,15 @@ namespace Encompass
existingComponentStore.FinishRegistering(); existingComponentStore.FinishRegistering();
pendingComponentStore.FinishRegistering(); pendingComponentStore.FinishRegistering();
UpToDateComponentStore.FinishRegistering(); UpToDateComponentStore.FinishRegistering();
pendingMask = new BitArray(typeToIndex.Count);
readMask = new BitArray(typeToIndex.Count);
withMask = new BitArray(typeToIndex.Count);
withoutMask = new BitArray(typeToIndex.Count);
notWithMask = new BitArray(typeToIndex.Count);
solverArrayA = new BitArray(typeToIndex.Count);
solverArrayB = new BitArray(typeToIndex.Count);
solverArrayC = new BitArray(typeToIndex.Count);
} }
internal void Clear() internal void Clear()
@ -197,60 +216,60 @@ namespace Encompass
internal IEnumerable<Entity> QueryEntities(IEnumerable<Entity> entities, HashSet<Type> readTypes, HashSet<Type> readPendingTypes, IEnumerable<Type> withTypes, IEnumerable<Type> withoutTypes) internal IEnumerable<Entity> QueryEntities(IEnumerable<Entity> entities, HashSet<Type> readTypes, HashSet<Type> readPendingTypes, IEnumerable<Type> withTypes, IEnumerable<Type> withoutTypes)
{ {
var pendingMask = new BitArray(typeToIndex.Count); pendingMask.SetAll(false);
foreach (var type in readPendingTypes) foreach (var type in readPendingTypes)
{ {
pendingMask.Set(typeToIndex[type], true); pendingMask.Set(typeToIndex[type], true);
} }
var readMask = new BitArray(typeToIndex.Count); readMask.SetAll(false);
foreach (var type in readTypes) foreach (var type in readTypes)
{ {
readMask.Set(typeToIndex[type], true); readMask.Set(typeToIndex[type], true);
} }
var withMask = new BitArray(typeToIndex.Count); withMask.SetAll(false);
foreach (var type in withTypes) foreach (var type in withTypes)
{ {
withMask.Set(typeToIndex[type], true); withMask.Set(typeToIndex[type], true);
} }
var withoutMask = new BitArray(typeToIndex.Count); withoutMask.SetAll(false);
foreach (var type in withoutTypes) foreach (var type in withoutTypes)
{ {
withoutMask.Set(typeToIndex[type], true); withoutMask.Set(typeToIndex[type], true);
} }
notWithMask.SetAll(false);
notWithMask.Or(withMask).Not();
foreach (var entity in entities) foreach (var entity in entities)
{ {
var pendingEntity = pendingComponentStore.EntityBitArray(entity); var pendingEntity = pendingComponentStore.EntityBitArray(entity);
var existingEntity = existingComponentStore.EntityBitArray(entity); var existingEntity = existingComponentStore.EntityBitArray(entity);
if (VerifyTypes(pendingEntity, existingEntity, readMask, pendingMask, withMask, withoutMask)) { yield return entity; } if (VerifyTypes(pendingEntity, existingEntity, readMask, pendingMask, withMask, withoutMask, notWithMask)) { yield return entity; }
} }
} }
internal bool VerifyTypes(BitArray pendingEntity, BitArray existingEntity, BitArray readMask, BitArray pendingMask, BitArray withMask, BitArray withoutMask) internal bool VerifyTypes(BitArray pendingEntity, BitArray existingEntity, BitArray readMask, BitArray pendingMask, BitArray withMask, BitArray withoutMask, BitArray notWithMask)
{ {
var arrayA = new BitArray(typeToIndex.Count); solverArrayA.SetAll(false);
var arrayB = new BitArray(typeToIndex.Count); solverArrayB.SetAll(false);
var arrayC = new BitArray(typeToIndex.Count); solverArrayC.SetAll(false);
var notWithMask = new BitArray(typeToIndex.Count); solverArrayA.Or(pendingMask).And(withMask).And(pendingEntity);
notWithMask.Or(withMask).Not(); solverArrayB.Or(readMask).And(withMask).And(existingEntity);
solverArrayA.Or(solverArrayB).Or(notWithMask);
arrayA.Or(pendingMask).And(withMask).And(pendingEntity); solverArrayB.SetAll(false);
arrayB.Or(readMask).And(withMask).And(existingEntity); solverArrayB.Or(pendingMask).And(withoutMask).And(pendingEntity).Not();
arrayA.Or(arrayB).Or(notWithMask); solverArrayC.Or(readMask).And(withoutMask).And(existingEntity).Not();
solverArrayB.And(solverArrayC);
arrayB.SetAll(false); solverArrayA.And(solverArrayB);
arrayB.Or(pendingMask).And(withoutMask).And(pendingEntity).Not();
arrayC.Or(readMask).And(withoutMask).And(existingEntity).Not();
arrayB.And(arrayC);
arrayA.And(arrayB); return !solverArrayA.Cast<bool>().Contains(false);
return !arrayA.Cast<bool>().Contains(false);
} }
} }
} }