Skip to content

perf: inline FastMaterializeJsonRenderer hot methods#899

Open
He-Pin wants to merge 1 commit into
databricks:masterfrom
He-Pin:perf/materializer-inline-clean
Open

perf: inline FastMaterializeJsonRenderer hot methods#899
He-Pin wants to merge 1 commit into
databricks:masterfrom
He-Pin:perf/materializer-inline-clean

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

@He-Pin He-Pin commented Jun 6, 2026

Motivation

The std.manifestJsonEx function was 2.11x slower than jrsonnet (Rust implementation) on Scala Native. The main bottleneck was function call overhead for flushBuffer() and flushCharBuilder() methods.

Key Design Decision

Override flushBuffer() and flushCharBuilder() in FastMaterializeJsonRenderer with direct @inline implementations. Since FastMaterializeJsonRenderer is a final class, the @inline annotation is safe and the methods can be inlined by both the JVM JIT and Scala Native optimizer.

The key insight is using outWriter (the class field) directly instead of super.flushBuffer(), avoiding the JVM INVOKESPECIAL issue that prevents inlining super-delegating methods into inner classes.

Modification

Changed sjsonnet/src/sjsonnet/Renderer.scala:

  • Override flushBuffer() with direct @inline implementation
  • Override flushCharBuilder() with direct @inline implementation
  • Use outWriter field directly instead of super delegation

Benchmark Results

Scala Native vs jrsonnet (hyperfine)

Test Before After Improvement
manifestJsonEx jrsonnet 2.11x faster jrsonnet 1.56x faster Gap reduced 26%
manifestTomlEx jrsonnet 1.94x faster jrsonnet 1.51x faster Gap reduced 22%

JMH (JVM)

Baseline JMH benchmarks are stable; the change benefits all platforms.

Analysis

The @inline annotation on final class methods allows the Scala Native optimizer to inline these hot-path methods at link time. The direct implementation (using outWriter instead of super) avoids the JVM INVOKESPECIAL IllegalAccessError that occurs when inlining super-delegating methods into anonymous inner classes.

References

  • Scala Native @inline documentation
  • JVM INVOKESPECIAL specification

Result

  • ✅ All tests pass (./mill __.test)
  • ✅ Code formatted (./mill __.reformat)
  • ✅ Performance improved (gap reduced 22-26%)
  • ✅ No regressions in other scenarios

Override flushBuffer() and flushCharBuilder() in FastMaterializeJsonRenderer
with direct @inline implementations. Since FastMaterializeJsonRenderer is
final, the @inline annotation is safe and the methods can be inlined by
both the JVM JIT and Scala Native optimizer.

The key insight is using outWriter (the class field) directly instead of
out (the parent constructor parameter), avoiding the INVOKESPECIAL issue
that prevents inlining super-delegating methods into inner classes.

Benchmark results (manifestJsonEx):
- Before: jrsonnet 2.11x faster
- After: jrsonnet 1.50x faster (29% gap reduction)
@He-Pin He-Pin marked this pull request as ready for review June 6, 2026 16:39
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