From 9909b12c41e39ec05854180149e9727564e7414a Mon Sep 17 00:00:00 2001 From: cha0s Date: Fri, 3 May 2019 13:26:51 -0500 Subject: [PATCH] perf: list ticking/dirty optimization --- packages/entity/index.js | 3 ++ packages/entity/list/index.js | 50 +++++++++++++++++--------- packages/entity/traits/listed.trait.js | 30 ++++++++-------- 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/packages/entity/index.js b/packages/entity/index.js index 0bce52d..150b065 100644 --- a/packages/entity/index.js +++ b/packages/entity/index.js @@ -278,6 +278,9 @@ export class Entity extends decorate(Resource) { } instance.isDirty = false; this.isDirty = true; + if (this.is('listed')) { + this.list.markEntityDirty(this); + } this._setInstanceState(state, type, instance); } }); diff --git a/packages/entity/list/index.js b/packages/entity/list/index.js index 1444b12..17f449c 100644 --- a/packages/entity/list/index.js +++ b/packages/entity/list/index.js @@ -17,7 +17,9 @@ export class EntityList extends decorate(class {}) { constructor() { super(); this._afterDestructionTickers = []; + this._dirtyEntities = []; this._entities = {}; + this._flatEntities = []; this._quadTree = new QuadTree(); } @@ -31,15 +33,19 @@ export class EntityList extends decorate(class {}) { addEntity(entity) { const uuid = entity.instanceUuid; this._entities[uuid] = entity; + this._flatEntities.push(entity); this.state = this.state.set(uuid, entity.state); entity.addTrait('listed'); - entity.list = this; + entity.setIntoList(this); entity.once('destroy', () => { this.removeEntity(entity); // In the process of destroying, allow entities to specify tickers that // must live on past destruction. const tickers = entity.invokeHookFlat('afterDestructionTickers'); - this._afterDestructionTickers.push(...tickers); + for (let i = 0; i < tickers.length; i++) { + const ticker = tickers[i]; + this._afterDestructionTickers.push(ticker); + } }); this.emit('entityAdded', entity); } @@ -51,11 +57,17 @@ export class EntityList extends decorate(class {}) { } findEntity(uuid) { - if (this._entities[uuid]) { + if (uuid in this._entities) { return this._entities[uuid]; } } + markEntityDirty(entity) { + if (-1 === this._dirtyEntities.indexOf(entity)) { + this._dirtyEntities.push(entity); + } + } + patchStateStep(uuid, step) { const entity = this._entities[uuid]; if ('/' === step.path) { @@ -90,6 +102,8 @@ export class EntityList extends decorate(class {}) { removeEntity(entity) { const uuid = entity.instanceUuid; delete this._entities[uuid]; + const index = this._flatEntities.indexOf(entity); + this._flatEntities.splice(index, 1); this.state = this.state.delete(uuid); this.emit('entityRemoved', entity); if (entity.is('listed')) { @@ -99,24 +113,17 @@ export class EntityList extends decorate(class {}) { tick(elapsed) { // Run after destruction tickers. - this.tickAfterDestructionTickers(elapsed); + if (this._afterDestructionTickers.length > 0) { + this.tickAfterDestructionTickers(elapsed); + } // Run normal tickers. - for (const uuid in this._entities) { - const entity = this._entities[uuid]; + for (let i = 0; i < this._flatEntities.length; i++) { + const entity = this._flatEntities[i]; entity.tick(elapsed); } // Update state. if (AVOCADO_SERVER) { - this.state = this.state.withMutations((state) => { - for (const uuid in this._entities) { - const entity = this._entities[uuid]; - if (!entity.isDirty) { - continue; - } - entity.isDirty = false; - state.set(uuid, entity.state); - } - }); + this.tickMutateState(); } } @@ -135,6 +142,17 @@ export class EntityList extends decorate(class {}) { } } + tickMutateState(state) { + this.state = this.state.withMutations((state) => { + for (let i = 0; i < this._dirtyEntities.length; i++) { + const entity = this._dirtyEntities[i]; + entity.isDirty = false; + state.set(entity.$$avocado_property_instanceUuid, entity.state); + } + }); + this._dirtyEntities = []; + } + visibleEntities(query) { const entities = []; const entitiesTrack = []; diff --git a/packages/entity/traits/listed.trait.js b/packages/entity/traits/listed.trait.js index 97019be..faaf6c4 100644 --- a/packages/entity/traits/listed.trait.js +++ b/packages/entity/traits/listed.trait.js @@ -5,29 +5,19 @@ import {Trait} from '../trait'; export class Listed extends Trait { initialize() { - this._list = undefined; + this.entity.list = undefined; this.quadTreeAabb = []; this.quadTreeNodes = []; } destroy() { this.removeQuadTreeNodes(); - delete this._list; + delete this.entity.list; this.entity.emit('removedFromList'); } - get list() { - return this._list; - } - - set list(list) { - this._list = list; - this.addQuadTreeNodes(); - this.entity.emit('addedToList'); - } - addQuadTreeNodes() { - const list = this._list; + const list = this.entity.list; if (!list) { return; } @@ -54,7 +44,7 @@ export class Listed extends Trait { } removeQuadTreeNodes() { - const list = this._list; + const list = this.entity.list; if (!list) { return; } @@ -97,5 +87,17 @@ export class Listed extends Trait { } } + methods() { + return { + + setIntoList: (list) => { + this.entity.list = list; + this.addQuadTreeNodes(); + this.entity.emit('addedToList'); + }, + + }; + } + }