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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions