Skip to content

Add CLR ProxyHandler lanes to ProxyBenchmark#2680

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:proxy-clr-handler-benchmarks
Jul 13, 2026
Merged

Add CLR ProxyHandler lanes to ProxyBenchmark#2680
lahma merged 1 commit into
sebastienros:mainfrom
lahma:proxy-clr-handler-benchmarks

Conversation

@lahma

@lahma lahma commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #2678: adds six lanes exercising the new CLR ProxyHandler path, 1:1 mirrors of the existing JS-handler lanes (same target objects, same script shapes and iteration counts) so the columns compare directly:

  • ClrTrapGet / ClrTrapSet / ClrTrapHas — C# handler implementing the same semantics as the JS { get, set, has } handler
  • ClrForwardGet — handler with no overrides (pure forward through the CLR branch)
  • ClrApplyTrap / ClrConstructTrap — C# apply/construct traps over the same function target

This puts numbers behind #2678's "the CLR path skips trap-name lookup and argument arrays" claim and guards the new dispatch branch against regressions. Each lane is warm-evaluated once in GlobalSetup with its numeric result asserted, so a wrong-semantics lane fails loudly instead of benchmarking garbage.

No product code changes. Measured comparison table to follow as a comment (runs are done serially, nothing else on the machine).

🤖 Generated with Claude Code

https://claude.ai/code/session_01EsHuKuE4UihKZp5HYapDHE

@lahma
lahma enabled auto-merge (squash) July 13, 2026 22:11
@lahma

lahma commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Measured comparison (same run, serial, DefaultJob — medians):

Operation JS handler CLR ProxyHandler Δ time Allocated
Get trap 19.14 ms 6.79 ms −65% 1.33 KB = 1.33 KB
Set trap 25.93 ms 7.54 ms −71% 2,806 KB = 2,806 KB
Has trap 16.34 ms 5.17 ms −68% 1.33 KB = 1.33 KB
Forward (no trap) get 6.67 ms 5.71 ms −15% 1.33 KB = 1.33 KB
Apply trap 51.16 ms 28.49 ms −44% 20,455 KB → 14,205 KB (−31%)
Construct trap 2.76 ms 1.44 ms −47% 2,579 KB → 2,970 KB*

The CLR path skips the per-operation trap-name property lookup, the trap argument array, and (for apply) the CreateArrayFromList packing — hence the ~3× on the property traps and the −31% allocation on apply. *Construct allocates slightly more here because the C# handler builds its result JsObject directly, which is part of the measured lane.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EsHuKuE4UihKZp5HYapDHE

Extend ProxyBenchmark with six lanes exercising the new public CLR trap
API (Jint.Runtime.Interop.ProxyHandler + engine.Advanced.CreateProxy):
ClrTrapGet, ClrTrapSet, ClrTrapHas, ClrForwardGet, ClrApplyTrap and
ClrConstructTrap. Each is a 1:1 mirror of the corresponding JS-handler
lane (same targets, same prepared-script shape and iteration counts) so
the columns compare JS-handler versus CLR-handler trap dispatch directly.

The handlers mirror the JS setup semantically: TrappingClrHandler
implements get/set/has via target.Get/Set/HasProperty,
ForwardingClrHandler overrides nothing (pure forward), and
ApplyClrHandler invokes the target through Engine.Call and constructs a
plain JsObject with property v. GlobalSetup warm-evaluates the new lanes
and asserts their numeric results, throwing on any trap-wiring mismatch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsHuKuE4UihKZp5HYapDHE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant