Skip to content

perf: std.manifestJsonEx is 1.74× slower than jrsonnet #848

@He-Pin

Description

@He-Pin

Tracking issue for a specific perf gap found while comparing sjsonnet (native, master) against jrsonnet (master). Parent comparison: #666.

Observation

std.manifestJsonEx is 1.74× slower than jrsonnet.

Scenario: bench/resources/go_suite/manifestJsonEx.jsonnet.

mean min
sjsonnet (native) 4.7 ± 0.9 ms 3.3 ms
jrsonnet 2.7 ± 0.9 ms 1.5 ms

Repro:

hyperfine --warmup 2 --runs 20 -N \
  "sjsonnet bench/resources/go_suite/manifestJsonEx.jsonnet" \
  "jrsonnet bench/resources/go_suite/manifestJsonEx.jsonnet"

Code

sjsonnet/src/sjsonnet/stdlib/ManifestModule.scala:76-105ManifestJsonEx. Calls Materializer.apply0(v, MaterializeJsonRenderer(...))(ev).toString.

Hypothesis

Two-stage rendering:

  1. Materializer walks the Val tree and feeds a ujson visitor (which builds a ujson.Value or streams to a writer depending on the renderer).
  2. Output is collected into a StringWriter, then .toString copies the buffer into a new String, then Val.Str wraps it.

Each visitor call is a virtual dispatch. For the nested test object this is ~40–50 visits + indent logic.

jrsonnet appears to render directly from its Val to a String/IStr in a single pass, without an intermediate visitor AST.

Directions

  • Specialize ManifestJsonEx to walk the Val tree directly and emit to a single CharBuilder / StringBuilder — skipping the Materializer + ujson indirection entirely. The main tradeoff is code duplication with the renderer — could be mitigated by sharing escape/number utilities.
  • Since kube-prometheus (real-world) ends up materializing large JSON, this gap likely contributes to the ~2.8× real-world gap identified in performance optimization #666. High-impact.

Part of the jrsonnet-parity effort tracked in #666.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions