Tracking issue for the QuickJS interop hot-path performance work, implemented from an audit of the shipped-app runtime hot path (native / QuickJS interpreter). Findings are labeled A-F. Work spans three repos; commit refs are noted per item.
Done
(Prior related work, before this audit pass: a6e6eba delivered the GC delta-gate, per-element pointer + wheel fast paths, and batched task drain.)
Deferred (intentional)
Next pickup (broader structural tier, not part of the A-F audit)
I2 (general cached-delegate invokers for the reflection slow path) - dropped as a standalone item. It does not survive scrutiny: Expression.Compile is not AOT-safe (IL2CPP, i.e. the no-JIT native targets QuickJS exists for), and Delegate.CreateDelegate can't be invoked generically without DynamicInvoke (slower than reflection). The AOT-safe way to get broad fast invokers is FastPath registration, ideally automated by F (a source generator). So I2 folds into F + FastPath expansion rather than being a separate runtime-delegate layer. The remaining reflection hits after D/E/C/B are the cold long tail anyway.
Notes
Architectural lessons worth keeping: FastPath instance methods key by concrete runtime type; ctors key by type name (keying-safe); Expression.Compile is not AOT-safe, so S1 uses a static typed-setter switch rather than compiled delegates.
Tracking issue for the QuickJS interop hot-path performance work, implemented from an audit of the shipped-app runtime hot path (native / QuickJS interpreter). Findings are labeled A-F. Work spans three repos; commit refs are noted per item.
Done
PainterBridgereplays a flat command buffer ontoPainter2Din one JS->C# crossing instead of one reflection crossing per op (and pernew Vector2/new Color). JS-sidePainterrecorder +batchedVisualContent/useBatchedVectorContent.393d426, onejs-reactfeeb7fd, Websitec20d0e2InteropValuepacking as the reflection ctor path, so JS sees an identical value.393d426VisualElement.Addcan't be seeded for Button/Label/etc.):VisualElement.Add/Insert/RemoveFromHierarchy->NodeBridge(static, registered by type name, type-agnostic).StyleBridgetyped setters (S1).393d426, onejs-reactfeeb7fdFindElementHandle's parent-chain walk now runs under a single lock acquisition (GetHandleForElementOrAncestor) instead of one lock + dict lookup per hop. Behavior-identical; collapses N locks to 1 on deep (composite-control) event targets.fbc379f(Prior related work, before this audit pass:
a6e6ebadelivered the GC delta-gate, per-element pointer + wheel fast paths, and batched task drain.)Deferred (intentional)
ExecutePendingJobsafter every event dispatch. pointermove is already throttled to ~1/frame, and each drain is load-bearing (dispatch returns the suppression-flag bitmask synchronously, so the reconcile must complete per event). Real but low value, with correctness risk. Revisit only if a profiler flags it.[OneJSFastPath]attribute / source generator would remove the re-register-in-Awake step. DX-only (built-in registrations self-heal on domain reload), but it is also the AOT-safe path to broad fast member invocation (see the I2 note below). Defer until custom FastPath usage is common or I2-style coverage is wanted.Next pickup (broader structural tier, not part of the A-F audit)
I2 (general cached-delegate invokers for the reflection slow path) - dropped as a standalone item. It does not survive scrutiny:
Expression.Compileis not AOT-safe (IL2CPP, i.e. the no-JIT native targets QuickJS exists for), andDelegate.CreateDelegatecan't be invoked generically withoutDynamicInvoke(slower than reflection). The AOT-safe way to get broad fast invokers is FastPath registration, ideally automated by F (a source generator). So I2 folds into F + FastPath expansion rather than being a separate runtime-delegate layer. The remaining reflection hits after D/E/C/B are the cold long tail anyway.Notes
Architectural lessons worth keeping: FastPath instance methods key by concrete runtime type; ctors key by type name (keying-safe);
Expression.Compileis not AOT-safe, so S1 uses a static typed-setter switch rather than compiled delegates.