Skip to content

Commit 883c173

Browse files
Fix performance regression by using hybrid immediate resolution approach
- Remove pendingReferences system that caused 75% performance drop - Restore proven closure-based approach for deferred resolution - Maintain immediate resolution optimization for cache hits - Preserve all error handling and reference type support Co-Authored-By: Harry Brundage <[email protected]>
1 parent ed10e9b commit 883c173

File tree

1 file changed

+38
-30
lines changed

1 file changed

+38
-30
lines changed

src/fast-instantiator.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ export class InstantiatorBuilder<T extends IClassModelType<Record<string, IAnyTy
9494
const context = {
9595
referenceCache: new Map(),
9696
referencesToResolve: [],
97-
pendingReferences: [],
9897
env,
9998
};
10099
@@ -105,18 +104,6 @@ export class InstantiatorBuilder<T extends IClassModelType<Record<string, IAnyTy
105104
}
106105
context.referencesToResolve = null;
107106
108-
if (context.pendingReferences) {
109-
for (const ref of context.pendingReferences) {
110-
const referencedInstance = context.referenceCache.get(ref.identifier);
111-
if (referencedInstance) {
112-
ref.instance[ref.property] = referencedInstance;
113-
} else if (ref.isRequired) {
114-
throw new Error(\`can't resolve reference for property "\${ref.property}" using identifier \${ref.identifier}\`);
115-
}
116-
}
117-
context.pendingReferences = null;
118-
}
119-
120107
return instance;
121108
};
122109
@@ -233,25 +220,46 @@ export class InstantiatorBuilder<T extends IClassModelType<Record<string, IAnyTy
233220
`;
234221
}
235222

236-
return `
237-
// setup reference for ${key} with closure-free resolution
238-
const ${varName} = snapshot?.["${key}"];
239-
if (${varName}) {
240-
const referencedInstance = context.referenceCache.get(${varName});
241-
if (referencedInstance) {
242-
this["${key}"] = referencedInstance;
243-
} else {
244-
if (!context.pendingReferences) {
245-
context.pendingReferences = [];
223+
let resolve;
224+
if (isSafeReference) {
225+
resolve = `
226+
if (${varName}) {
227+
const referencedInstance = context.referenceCache.get(${varName});
228+
if (referencedInstance) {
229+
this["${key}"] = referencedInstance;
230+
} else {
231+
context.referencesToResolve.push(() => {
232+
const deferredInstance = context.referenceCache.get(${varName});
233+
if (deferredInstance) {
234+
this["${key}"] = deferredInstance;
235+
}
236+
});
246237
}
247-
context.pendingReferences.push({
248-
instance: this,
249-
property: "${key}",
250-
identifier: ${varName},
251-
isRequired: ${isRequiredReference}
252-
});
253238
}
254-
}
239+
`;
240+
} else if (isRequiredReference) {
241+
resolve = `
242+
if (${varName}) {
243+
const referencedInstance = context.referenceCache.get(${varName});
244+
if (referencedInstance) {
245+
this["${key}"] = referencedInstance;
246+
} else {
247+
context.referencesToResolve.push(() => {
248+
const deferredInstance = context.referenceCache.get(${varName});
249+
if (deferredInstance) {
250+
this["${key}"] = deferredInstance;
251+
} else {
252+
throw new Error(\`can't resolve reference for property "${key}" using identifier \${${varName}}\`);
253+
}
254+
});
255+
}
256+
}
257+
`;
258+
}
259+
260+
return `
261+
const ${varName} = snapshot?.["${key}"];
262+
${resolve}
255263
`;
256264
}
257265

0 commit comments

Comments
 (0)