perf: optimize std.makeArray for constant-body functions#697
Draft
He-Pin wants to merge 1 commit intodatabricks:masterfrom
Draft
perf: optimize std.makeArray for constant-body functions#697He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin wants to merge 1 commit intodatabricks:masterfrom
Conversation
cf00ce9 to
a0be13f
Compare
Detect when the function passed to std.makeArray ignores its index parameter and always returns the same expression. In that case, evaluate the body once and fill the array with the same Lazy reference, avoiding N-1 redundant evaluations. Detection uses Val.Func.isNonCapturing on bodyExpr to identify constant bodies (literals, non-capturing expressions). Upstream: jit branch commit 0e2bbe9e
a0be13f to
9d6a0f2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
std.makeArray(n, func)creates an array of sizenby callingfunc(i)for each indexi. When the function body is a constant (e.g.,std.makeArray(1000, function(_) 'x')), every element gets the same value, but the current implementation still createsnlazy thunks (LazyApply1) andnVal.Numindex values — all of which are immediately discarded when evaluated.Key Design Decision
Detect constant-body functions at call time using the existing
bodyExpraccessor. Whenfunc.bodyExpris aVal.Literal(a value that is both aValand anExpr), fill the array directly withjava.util.Arrays.fill— zero lazy thunks, zeroVal.Numallocations.Modification
sjsonnet/src/sjsonnet/stdlib/ArrayModule.scala(std.makeArray):func.params.names.length == 1 && func.bodyExpr != null && body.isInstanceOf[Val.Literal]java.util.Arrays.fill(a, constVal)— O(1) work per elementLazyApply1loopsjsonnet/src/sjsonnet/Val.scala:bodyExprdoc to mention this optimizationBenchmark Results
JMH — Full Suite (35 benchmarks, @fork(1) @WarmUp(1) @measurement(1))
No regressions across all 35 benchmarks.
Analysis of Key Improvements
std.foldloverstd.makeArray(20000, function(i) 'aaaaa')): The constant-body detection eliminates 20,000LazyApply1thunks and 20,000Val.Numallocations.std.makeArrayfeeds intostd.foldl.std.makeArraywith constant body to build string arrays.Analysis
bodyExpris a simple accessor (returns null by default). TheisInstanceOfcheck is a single vtable lookup.Val.Literalvalues are immutable and safe to share across array elements.Arrays.fill: JDK-optimized bulk fill — handles the entire array in a single call.LazyApply1path unchanged.References
Val.Literal— values that extend bothValandExpr(literals liketrue,false,null, string constants)bodyExpraccessor introduced forstd.foldlstring concat optimizationResult
Zero-allocation array initialization for constant-body
std.makeArray. 50-65% improvement on benchmarks usingstd.makeArraywith constant functions.