Skip to content

perf: Node IPC binary framing to avoid JSON-encoding large HTML payloads #1181

Description

@zeroedin

Context

Follow-up from #1180. The Node bridge has the same 4-pass JSON serialization overhead as QuickJS for onPageRendered payloads — EncodeMessage embeds the full ~800KB HTML inside a JSON envelope, requiring JSON escaping on encode and unescaping on decode on both Go and Node sides.

The QuickJS path is addressed in #1180 via native object construction. The Node path requires IPC protocol changes and is tracked separately here.

Current Node IPC path

CallHookbridge.Send(&Message{Payload: HookRenderedPayload{...}})EncodeMessage:

  1. Go: jsonCodec.Marshal(msg) — JSON-encodes ~800KB HTML (escaping ", <, >, \n, etc.)
  2. Node: JSON.parse(body) — parses the full JSON including escaped HTML
  3. Node: Hook runs, returns object
  4. Node: JSON.stringify(result) — re-encodes ~800KB HTML
  5. Go: jsonCodec.Unmarshal(body, &resp) — parses it back

Why it's lower priority than #1180

  • BatchCallHook distributes pages across the worker pool — per-page overhead is amortized across CPU cores
  • QuickJS is single-threaded, so the QuickJS fix has higher wall-clock impact
  • Protocol changes touch EncodeMessage/DecodeMessage (Go), the Node-side bridge JS message handler, and the Message struct — higher blast radius

Possible approaches

  1. Split-message framing: Send a small JSON metadata message ({ frontMatter, url, path, htmlLength: N }) followed by N bytes of raw HTML. Avoids JSON-encoding the HTML body entirely.
  2. Length-prefixed binary fields: Extend the LSP-style framing to support binary fields — the JSON envelope references a field by name, and the raw bytes follow the JSON body.
  3. Base64 encoding: Simpler than protocol changes but only reduces overhead ~33% (base64 inflation vs JSON escaping). Not recommended.

Refs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions