Improve mass deletion performance

This commit is contained in:
tobspr 2020-09-19 08:51:28 +02:00
parent b7c773a70e
commit 5bdf6386a1
4 changed files with 269 additions and 239 deletions

View File

@ -93,14 +93,6 @@ export class Entity extends BasicSerializableObject {
return clone;
}
/**
* Internal destroy callback
*/
internalDestroyCallback() {
assert(!this.destroyed, "Can not destroy entity twice");
this.destroyed = true;
}
/**
* Adds a new component, only possible until the entity is registered on the entity manager,
* after that use @see EntityManager.addDynamicComponent

View File

@ -155,6 +155,24 @@ export class EntityManager extends BasicSerializableObject {
return null;
}
/**
* Returns a map which gives a mapping from UID to Entity.
* This map is not updated.
*
* @returns {Map<number, Entity>}
*/
getFrozenUidSearchMap() {
const result = new Map();
const array = this.entities;
for (let i = 0, len = array.length; i < len; ++i) {
const entity = array[i];
if (!entity.queuedForDestroy && !entity.destroyed) {
result.set(entity.uid, entity);
}
}
return result;
}
/**
* Returns all entities having the given component
* @param {typeof Component} componentHandle
@ -206,7 +224,7 @@ export class EntityManager extends BasicSerializableObject {
this.unregisterEntityComponents(entity);
entity.registered = false;
entity.internalDestroyCallback();
entity.destroyed = true;
this.root.signals.entityDestroyed.dispatch(entity);
}

View File

@ -88,15 +88,16 @@ export class GameSystemWithFilter extends GameSystem {
}
refreshCaches() {
this.allEntities.sort((a, b) => a.uid - b.uid);
// Remove all entities which are queued for destroy
for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i];
if (entity.queuedForDestroy || entity.destroyed) {
this.allEntities.splice(i, 1);
i -= 1;
}
}
this.allEntities.sort((a, b) => a.uid - b.uid);
}
/**

View File

@ -48,6 +48,9 @@ export class HUDMassSelector extends BaseHUDPart {
* @param {Entity} entity
*/
onEntityDestroyed(entity) {
if (this.root.bulkOperationRunning) {
return;
}
this.selectedUids.delete(entity.uid);
}
@ -90,14 +93,30 @@ export class HUDMassSelector extends BaseHUDPart {
doDelete() {
const entityUids = Array.from(this.selectedUids);
// Build mapping from uid to entity
/**
* @type {Map<number, Entity>}
*/
const mapUidToEntity = this.root.entityMgr.getFrozenUidSearchMap();
this.root.logic.performBulkOperation(() => {
for (let i = 0; i < entityUids.length; ++i) {
const uid = entityUids[i];
const entity = this.root.entityMgr.findByUid(uid);
const entity = mapUidToEntity.get(uid);
if (!entity) {
logger.error("Entity not found by uid:", uid);
continue;
}
if (!this.root.logic.tryDeleteBuilding(entity)) {
logger.error("Error in mass delete, could not remove building");
this.selectedUids.delete(uid);
}
}
});
// Clear uids later
this.selectedUids = new Set();
}
startCopy() {