From b23c2fd5fe38fff999be59a4d569730bbf6572cb Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Sat, 24 Oct 2026 23:57:19 +0200 Subject: [PATCH] perf(builtin): remember the last field reference fieldRef keeps each field reference in a map in a WeakMap, so that taking the address of a field always gives the same pointer, and each call looks up both maps. A loop usually takes the address of the same field again and again, for example through a method that returns &s.field, as Cogent Lab tensors' Shape method does for every element access. Remember the target, key and reference of the last call, and return the reference without the lookups when they match. References are never replaced, so it is always the one the maps hold. Accessing a tensor element through Shape() takes 24 ns instead of 33 ns under Node 26. Signed-off-by: Randall C. O'Reilly --- gs/builtin/runtime-contract.test.ts | 19 +++++++++++++++++++ gs/builtin/varRef.ts | 25 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/gs/builtin/runtime-contract.test.ts b/gs/builtin/runtime-contract.test.ts index 4665edbfd..08cb57a3b 100644 --- a/gs/builtin/runtime-contract.test.ts +++ b/gs/builtin/runtime-contract.test.ts @@ -558,6 +558,25 @@ describe('builtin runtime contract helpers', () => { ) }) + it('returns the same field reference across interleaved fieldRef calls', () => { + // The last reference is cached, which must not change which reference + // each target and field gets. + const a = { x: 1, y: 2 } + const b = { x: 3, y: 4 } + const ax = fieldRef(a, 'x') + const bx = fieldRef(b, 'x') + const ay = fieldRef(a, 'y') + expect(fieldRef(a, 'x')).toBe(ax) + expect(fieldRef(a, 'x')).toBe(ax) + expect(fieldRef(b, 'x')).toBe(bx) + expect(fieldRef(a, 'y')).toBe(ay) + expect(ax).not.toBe(bx) + expect(ax).not.toBe(ay) + ax.value = 5 + expect(a.x).toBe(5) + expect(fieldRef(a, 'x').value).toBe(5) + }) + it('matches struct map keys by Go comparable value', () => { class Key { declare public name: string diff --git a/gs/builtin/varRef.ts b/gs/builtin/varRef.ts index 4ee848f4e..17472fe6f 100644 --- a/gs/builtin/varRef.ts +++ b/gs/builtin/varRef.ts @@ -123,6 +123,31 @@ export function varRef(v: T): VarRef { export function fieldRef( target: T, key: K, +): VarRef { + // A loop usually takes the address of the same field again and again, as + // a method returning &s.field does, so the last reference is remembered, + // which avoids the two map lookups. References are never replaced, so it + // is always the one that the maps hold. + if (target === lastFieldTarget && key === lastFieldKey) { + return lastFieldRef as VarRef + } + const ref = fieldRefLookup(target, key) + lastFieldTarget = target + lastFieldKey = key + lastFieldRef = ref + return ref +} + +// lastFieldTarget, lastFieldKey and lastFieldRef are the arguments and result +// of the last fieldRef call. Only this one target is kept alive by them. +let lastFieldTarget: object | undefined +let lastFieldKey: PropertyKey | undefined +let lastFieldRef: VarRef | undefined + +// fieldRefLookup finds or makes the reference of fieldRef in fieldReferences. +function fieldRefLookup( + target: T, + key: K, ): VarRef { let references = fieldReferences.get(target) if (references === undefined) {