Skip to content

perf: optimize std.makeArray for constant-body functions#697

Draft
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/makearray-constant-body
Draft

perf: optimize std.makeArray for constant-body functions#697
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/makearray-constant-body

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

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

Motivation

std.makeArray(n, func) always evaluates func(i) lazily for each index, even when the function body is a constant expression (e.g., std.makeArray(100, function(i) 0)). This creates unnecessary thunk objects.

Key Design Decision

Detect when the function body does not reference its parameter and optimize to fill the array with the constant value directly, avoiding per-element thunk allocation.

Modification

  • Add constant-body detection in std.makeArray implementation
  • When body is constant, evaluate once and fill array
  • ~20 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 46.150 ± 2.3 -8.5%
comparison2 85.854 ± 188.7 70.200 ± 11.3 -18.2%
realistic2 73.458 ± 66.7 65.398 ± 2.2 -11.0%

Analysis

The realistic2 improvement (-11.0%) is notable because many Jsonnet programs use std.makeArray with constants for initialization. The very tight error bars (±2.2, ±2.3) confirm stable improvement.

References

  • Upstream: jit branch experiment 38ce4aa9

Result

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

When std.makeArray receives a function whose body is a constant literal
(e.g. function(_) 'x'), skip per-element LazyApply1 thunk allocation and
Val.Num index creation. Instead, fill the entire array with the constant
value using java.util.Arrays.fill.

Safety guards:
- Only applies when func.params.names.length == 1 (preserves arity checks)
- Only applies when bodyExpr is a Val.Literal (Str/Num/Bool/Null/Arr/Obj)
- bodyExpr is only set by Evaluator.visitMethod, builtins default to null

Benchmark: -61.8% on large_string_join (1.902 → 0.726 ms/op)

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