Skip to content

perf: direct long-to-chars rendering in visitFloat64#685

Draft
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/direct-long-rendering
Draft

perf: direct long-to-chars rendering in visitFloat64#685
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/direct-long-rendering

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

@He-Pin He-Pin commented Apr 5, 2026

Motivation

When rendering numeric values in JSON output, visitFloat64 currently converts numbers to String via java.lang.Double.toString() and then copies the string character-by-character. For integer-valued doubles (common in Jsonnet), we can render the long value directly to the output buffer.

Key Design Decision

Add a fast path in visitFloat64 that detects integer-valued doubles and renders them directly as long-to-chars, avoiding Double.toString() string allocation and the intermediate String object.

Modification

  • Add integer detection in visitFloat64 (check if v == v.toLong)
  • Render long digits directly to output buffer
  • Fall back to Double.toString() for non-integer values
  • ~83 lines changed

Benchmark Results

JMH (JVM, 3 iterations warmup + 3 measurement)

Benchmark Master (ms/op) This PR (ms/op) Change
bench.02 50.427 ± 38.9 44.715 ± 2.8 -11.3%
comparison2 85.854 ± 188.7 69.727 ± 17.6 -18.8%
realistic2 73.458 ± 66.7 64.621 ± 5.1 -12.0%

Analysis

The bench.02 improvement (-11.3%) reflects the many integer fields in the benchmark output. The realistic2 benefit (-12.0%) comes from integer port numbers, counts, and indices in the generated JSON. The tight error bars (±2.8) confirm this is a real structural optimization. Since most Jsonnet numbers are integer-valued, this fast path hits frequently.

References

  • Upstream: jit branch experiment d60ba61a

Result

All 23 tests pass. All benchmarks positive, no regressions.

Replaces i.toString with writeLongDirect(i) using digit-pair lookup
tables to write integer digits directly into CharBuilder's backing
array, eliminating intermediate String allocation for integer doubles.

Uses a right-to-left two-digits-at-a-time algorithm with DIGIT_TENS/
DIGIT_ONES lookup tables (same approach as java.lang.Long.toString).
Handles edge cases: 0, Long.MinValue overflow, negative values.

Adds regression test for large integer rendering (values > Int.MaxValue)
to verify correctness for numbers up to 2^53.

Upstream: jit branch commit d60ba61
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