Skip to content

perf: optimize std.range allocation and add staticNull singleton#669

Open
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/range-allocation-staticnull
Open

perf: optimize std.range allocation and add staticNull singleton#669
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/range-allocation-staticnull

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

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

Motivation

Two allocation hot spots:

  1. std.range: Uses (from to to).map(i => Val.Num(pos, i)).toArray which creates a Scala Range, maps to an intermediate collection, then converts to Array. For large ranges, this is wasteful.
  2. Implicit-else null: Every if-then without else allocates a fresh Val.Null(e.pos). In hot loops with conditional logic, this creates garbage.

Key Design Decision

  • Long arithmetic prevents integer overflow (e.g. std.range(0, 2147483647) now produces a proper error instead of silently wrapping)
  • Val.staticNull singleton follows the existing staticTrue/staticFalse pattern
  • PrettyYamlRenderer null guard handles Position with null file (from staticNull and staticTrue/staticFalse)

Modification

1. std.range while-loop with overflow protection

val sizeLong = toInt.toLong - fromInt.toLong + 1L
val size = if (sizeLong <= 0) 0
else if (sizeLong > Int.MaxValue) Error.fail("std.range result too large")
else sizeLong.toInt
val arr = new Array[Eval](size)
var i = 0
while (i < size) {
  arr(i) = Val.Num(pos, fromInt + i)
  i += 1
}

2. Val.staticNull singleton

Following the existing staticTrue/staticFalse pattern, adds a singleton null for implicit-else results where position is not meaningful.

3. PrettyYamlRenderer null guard

Added current.currentFile != null check in saveCurrentPos() to handle Position with null file (from staticNull and staticTrue/staticFalse).

Benchmark Results

JMH Regression Suite (1 fork, 3 warmup, 1 measurement iteration)

Benchmark Master (ms/op) This PR (ms/op) Change
comparison 22.695 21.744 -4.2%
base64_byte_array 1.410 1.358 -3.7%
bench.02 47.049 45.548 -3.2%
realistic2 69.406 68.970 -0.6%
bench.06 0.358 0.363 +1.4%
comparison2 69.084 68.188 -1.3%
foldl 9.106 9.125 +0.2%

All 35 benchmarks within ±5% noise margin. This is an incremental building-block optimization.

Scala Native Hyperfine

This optimization reduces allocation overhead for std.range and implicit-else, which are building-block improvements that compound with other optimizations (comprehension scope reuse, foldl while-loops, etc.). In isolation, native impact is within noise.

Analysis

The std.range while-loop and staticNull singleton are foundational improvements that reduce allocation pressure. While individual JMH impact is within noise, these changes enable downstream optimizations (e.g., comprehension scope reuse in PR #675/#686 benefits from reduced range allocation). The overflow protection with long arithmetic is a correctness improvement that prevents silent integer wrapping for edge cases.

References

Upstream: jit branch commit c4ee6be7 (range optimization + staticNull). Overflow fix added for correctness.

Upstream jit branch exploration at he-pin/sjsonnet@jit

Result

Incremental building-block optimization with no regressions. Reduces allocation overhead for std.range and implicit-else null. Adds overflow protection for large ranges.

Three targeted optimizations:

1. std.range: Replace Scala Range.map.toArray with direct while-loop
   array allocation. Avoids boxing through Range and .map intermediates.

2. Val.staticNull: Add singleton null value for runtime results where
   position information is not meaningful (e.g., if-then without else).
   Mirrors the existing staticTrue/staticFalse pattern.

3. visitIfElse: Use Val.staticNull instead of allocating new Val.Null
   instances for the implicit else branch.

Upstream: jit branch commit c4ee6be

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@He-Pin He-Pin marked this pull request as ready for review April 4, 2026 21:42
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