From 726f59f8608b51e988d961566f30669d894a977d Mon Sep 17 00:00:00 2001 From: babenhauserheide Date: Fri, 12 Mar 2021 10:52:59 +0100 Subject: [PATCH] Avoid quadratic behavior when validating sprites --- src/.internal/core/Registry.ts | 22 +++++++++++++++++++--- src/.internal/core/System.ts | 9 ++++++--- src/.internal/core/utils/Instance.ts | 1 + 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/.internal/core/Registry.ts b/src/.internal/core/Registry.ts index 6bb747f90..fd5537ef3 100644 --- a/src/.internal/core/Registry.ts +++ b/src/.internal/core/Registry.ts @@ -103,13 +103,22 @@ export class Registry { protected _placeholders: { [index: string]: string } = {}; /** - * A list of invalid(ated) [[Sprite]] objects that need to be re-validated + * Lists of invalid(ated) [[Sprite]] objects that need to be re-validated * during next cycle. * * @ignore Exclude from docs */ public invalidSprites: { [index: string]: Array } = {}; + /** + * Objects with the keys given by the uids of no longer + * invalid [[Sprite]] objects that should be removed from the + * invalid Sprites. + * + * @ignore Exclude from docs + */ + public validatedSpritesBatchPurge: { [index: string]: any } = {}; + /** * Components are added to this list when their data provider changes to * a new one or data is added/removed from their data provider. @@ -194,6 +203,7 @@ export class Registry { this.uid = this.getUniqueId(); this.invalidSprites.noBase = []; + this.validatedSpritesBatchPurge.noBase = {}; this.invalidDatas.noBase = []; this.invalidLayouts.noBase = []; this.invalidPositions.noBase = []; @@ -375,10 +385,16 @@ export class Registry { */ public removeFromInvalidSprites(sprite: Sprite) { if (sprite.baseId) { - $array.remove(this.invalidSprites[sprite.baseId], sprite); + if (!this.validatedSpritesBatchPurge[spriteBaseId][sprite.uid]) { + // not doing batch purge, so remove sprite from invalid sprites right here + $array.remove(this.invalidSprites[sprite.baseId], sprite); + } } - $array.remove(this.invalidSprites["noBase"], sprite); + if (!this.validatedSpritesBatchPurge[spriteBaseId][sprite.uid]) { + // not doing batch purge, so remove sprite from invalid sprites right here + $array.remove(this.invalidSprites["noBase"], sprite); + } } diff --git a/src/.internal/core/System.ts b/src/.internal/core/System.ts index 63849057e..54e47e906 100644 --- a/src/.internal/core/System.ts +++ b/src/.internal/core/System.ts @@ -273,8 +273,8 @@ export class System { $object.each(registry.invalidSprites, (key, invalidSprites) => { let count = 0; - - while (invalidSprites.length > 0) { + const toPurge = registry.validatedSpritesBatchPurge[key]; + for (const index = invalidSprites.length - 1; index >= 0; index--) { this.validateLayouts(key); this.validatePositions(key); @@ -287,9 +287,12 @@ export class System { count = 0; } - let sprite: Sprite = invalidSprites[invalidSprites.length - 1]; + let sprite: Sprite = invalidSprites[index]; // we need to check this, as validateLayout might validate sprite + if (sprite) { + toPurge[sprite.uid] = true; + } if (sprite && !sprite.isDisposed()) { if (!sprite._systemCheckIfValidate()) { // void diff --git a/src/.internal/core/utils/Instance.ts b/src/.internal/core/utils/Instance.ts index a03a2f17c..59e572b28 100644 --- a/src/.internal/core/utils/Instance.ts +++ b/src/.internal/core/utils/Instance.ts @@ -95,6 +95,7 @@ function createChild(htmlElement: $type.Optional