Skip to content

Hot-loop JS performance: JSON×10k is 14.8× slower than Bun in a warm isolate #37

Closed

Description

@hassidan

Summary

Process startup and memory are now consistently strong (v0.10.5 beats Node and Deno on all 22 validated apps, Bun on 17/22, 10.9 MiB RSS vs Bun 16.7 MiB). The remaining performance gap is steady-state JavaScript execution inside a warm isolate:

Workload (median of 90 calls, warm engine) Slice 0.10.5 Bun Node Deno
JSON.parse+stringify ×10,000 55.7 ms 3.8 ms 5.5 ms 4.0 ms
Numeric loop ×10,000 3.02 ms 0.40 ms 1.83 ms 1.66 ms

That is 14.8× slower than Bun on JSON (down from 30.9× in 0.9.9 — the monomorphic inline caches in the vendored Boa clearly helped) and 7.6× on numeric code that numeric_vm does not catch.

Why it matters

Slice's target workloads (per-request handlers, agent tool calls, tenant automations) are short — but "short" still includes parsing a 200 KB JSON body, running a template engine, or validating a schema with zod. At 15× those become the dominant cost and erase the startup advantage after a handful of requests.

Proposal — in order of cost/benefit

  1. Polymorphic inline caches (2–4 entry) for property get/set and method calls; the current IC is monomorphic (get_fast).
  2. Shape/hidden-class transitions with a transition tree so object literals built in a loop share shapes; most JSON-heavy code benefits immediately.
  3. Fast paths in JSON.parse/JSON.stringify operating on the shape table directly (the streaming JsonSeed parser is a start; stringify still walks generic property enumeration).
  4. Baseline JIT for hot CodeBlocks via cranelift — a 1:1 bytecode→machine-code translation without speculation keeps the attack surface small, keeps fuel metering exact (emit a counter decrement per basic block), and historically gives 2–5× over a bytecode interpreter.
  5. Publish a benchmarks/hot-loop/ micro-suite in CI so each of the above has a visible before/after.

Alternatively, document the trade-off explicitly: Slice is an interpreter by design (determinism, metering, memory safety) and hot-loop performance will stay in the interpreter class.

Activity

  1. siktec-lab commented on Nov 9, 2026

    @siktec-lab
    Collaborator

    Addressed in #41 (�0.10.6).

    • Added a direct Vec +
      yu_js + shape property-table (Shape::with_property_keys) fast-path for JSON.stringify and a zero-copy Latin1 borrow path for JSON.parse in �endor/boa_engine/src/builtins/json/mod.rs.
    • Added sub-millisecond monotonic performance.now() (__slice_perf_now).
    • Measured speedup: JSON.stringify x 10,000 improved 12.48x (60.0 ms -> 4.81 ms), and JSON.parse(JSON.stringify(obj)) x 10,000 improved 2.92x (94.0 ms -> 32.16 ms).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions