From 7c5381d26f22560c27aeef397367b71d3bf274f3 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Thu, 21 Nov 2024 23:47:27 +0900 Subject: [PATCH] perf: Slightly optimise object interner for larger codebase Signed-off-by: Naoki Ikeguchi --- .../src/emitter-framework/asset-emitter.ts | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/compiler/src/emitter-framework/asset-emitter.ts b/packages/compiler/src/emitter-framework/asset-emitter.ts index 77f7bf74d4..787e2a1163 100644 --- a/packages/compiler/src/emitter-framework/asset-emitter.ts +++ b/packages/compiler/src/emitter-framework/asset-emitter.ts @@ -860,14 +860,28 @@ function isDeclaration(type: Type): type is TypeSpecDeclaration | Namespace { * could consider. */ function createInterner() { + type PlainObject = Record; + const emptyObject = {}; - const knownObjects: Set> = new Set(); + const knownKeys = new Map>(); return { - intern>(object: T): T { - const keyLen = Object.keys(object).length; + intern(object: T): T { + const keys = Object.keys(object); + const keyLen = keys.length; if (keyLen === 0) return emptyObject as any; + // Find an object set with minimum size by object keys + let knownObjects = new Set(); + let minSize = Infinity; + for (const objs of keys.map((key) => knownKeys.get(key))) { + if (objs && objs.size < minSize) { + knownObjects = objs; + minSize = objs.size; + } + } + + // Now find a known object from the found smallest object set for (const ko of knownObjects) { const entries = Object.entries(ko); if (entries.length !== keyLen) continue; @@ -885,7 +899,16 @@ function createInterner() { } } - knownObjects.add(object); + // If the object is not known, add all keys as known + for (const key of keys) { + const ko = knownKeys.get(key); + if (ko) { + ko.add(object); + } else { + knownKeys.set(key, new Set([object])); + } + } + return object; }, };