Skip to content

chore: Make materializer stackless for obj and arr#620

Draft
He-Pin wants to merge 2 commits intodatabricks:masterfrom
He-Pin:materializer
Draft

chore: Make materializer stackless for obj and arr#620
He-Pin wants to merge 2 commits intodatabricks:masterfrom
He-Pin:materializer

Conversation

@He-Pin
Copy link
Contributor

@He-Pin He-Pin commented Mar 1, 2026

Motivation:
This can reduce some stack usage of the jvm native frame

refs:google/jsonnet#1142

based on #619

Which should be slightly slower? So I have to use a hybrid strategy.

on main

125] Benchmark                                                                  (path)  Mode  Cnt   Score   Error  Units
125] RegressionBenchmark.main             bench/resources/bug_suite/assertions.jsonnet  avgt        0.434          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.01.jsonnet  avgt        0.076          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.02.jsonnet  avgt       41.836          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.03.jsonnet  avgt       13.310          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.04.jsonnet  avgt       32.440          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.06.jsonnet  avgt        0.453          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.07.jsonnet  avgt        2.910          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.08.jsonnet  avgt        0.060          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.09.jsonnet  avgt        0.067          ms/op
125] RegressionBenchmark.main         bench/resources/cpp_suite/gen_big_object.jsonnet  avgt        0.998          ms/op
125] RegressionBenchmark.main      bench/resources/cpp_suite/large_string_join.jsonnet  avgt        2.000          ms/op
125] RegressionBenchmark.main  bench/resources/cpp_suite/large_string_template.jsonnet  avgt        2.384          ms/op
125] RegressionBenchmark.main             bench/resources/cpp_suite/realistic1.jsonnet  avgt        3.287          ms/op
125] RegressionBenchmark.main             bench/resources/cpp_suite/realistic2.jsonnet  avgt       75.854          ms/op
125] RegressionBenchmark.main                  bench/resources/go_suite/base64.jsonnet  avgt        0.846          ms/op
125] RegressionBenchmark.main            bench/resources/go_suite/base64Decode.jsonnet  avgt        0.650          ms/op
125] RegressionBenchmark.main       bench/resources/go_suite/base64DecodeBytes.jsonnet  avgt        9.567          ms/op
125] RegressionBenchmark.main       bench/resources/go_suite/base64_byte_array.jsonnet  avgt        1.495          ms/op
125] RegressionBenchmark.main              bench/resources/go_suite/comparison.jsonnet  avgt       23.110          ms/op
125] RegressionBenchmark.main             bench/resources/go_suite/comparison2.jsonnet  avgt       80.098          ms/op
125] RegressionBenchmark.main        bench/resources/go_suite/escapeStringJson.jsonnet  avgt        0.051          ms/op
125] RegressionBenchmark.main                   bench/resources/go_suite/foldl.jsonnet  avgt        9.389          ms/op
125] RegressionBenchmark.main             bench/resources/go_suite/lstripChars.jsonnet  avgt        0.652          ms/op
125] RegressionBenchmark.main          bench/resources/go_suite/manifestJsonEx.jsonnet  avgt        0.073          ms/op
125] RegressionBenchmark.main          bench/resources/go_suite/manifestTomlEx.jsonnet  avgt        0.090          ms/op
125] RegressionBenchmark.main         bench/resources/go_suite/manifestYamlDoc.jsonnet  avgt        0.076          ms/op
125] RegressionBenchmark.main                  bench/resources/go_suite/member.jsonnet  avgt        0.744          ms/op
125] RegressionBenchmark.main                bench/resources/go_suite/parseInt.jsonnet  avgt        0.053          ms/op
125] RegressionBenchmark.main                 bench/resources/go_suite/reverse.jsonnet  avgt       11.664          ms/op
125] RegressionBenchmark.main             bench/resources/go_suite/rstripChars.jsonnet  avgt        0.655          ms/op
125] RegressionBenchmark.main              bench/resources/go_suite/stripChars.jsonnet  avgt        0.635          ms/op
125] RegressionBenchmark.main                  bench/resources/go_suite/substr.jsonnet  avgt        0.164          ms/op
125/125, SUCCESS] ./mill bench.runRegressions 399s

with this

125] Benchmark                                                                  (path)  Mode  Cnt   Score   Error  Units
125] RegressionBenchmark.main             bench/resources/bug_suite/assertions.jsonnet  avgt        0.293          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.01.jsonnet  avgt        0.071          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.02.jsonnet  avgt       40.358          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.03.jsonnet  avgt       12.111          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.04.jsonnet  avgt       31.256          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.06.jsonnet  avgt        0.442          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.07.jsonnet  avgt        3.229          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.08.jsonnet  avgt        0.058          ms/op
125] RegressionBenchmark.main               bench/resources/cpp_suite/bench.09.jsonnet  avgt        0.066          ms/op
125] RegressionBenchmark.main         bench/resources/cpp_suite/gen_big_object.jsonnet  avgt        0.986          ms/op
125] RegressionBenchmark.main      bench/resources/cpp_suite/large_string_join.jsonnet  avgt        2.178          ms/op
125] RegressionBenchmark.main  bench/resources/cpp_suite/large_string_template.jsonnet  avgt        2.342          ms/op
125] RegressionBenchmark.main             bench/resources/cpp_suite/realistic1.jsonnet  avgt        2.983          ms/op
125] RegressionBenchmark.main             bench/resources/cpp_suite/realistic2.jsonnet  avgt       73.095          ms/op
125] RegressionBenchmark.main                  bench/resources/go_suite/base64.jsonnet  avgt        0.834          ms/op
125] RegressionBenchmark.main            bench/resources/go_suite/base64Decode.jsonnet  avgt        0.633          ms/op
125] RegressionBenchmark.main       bench/resources/go_suite/base64DecodeBytes.jsonnet  avgt        9.629          ms/op
125] RegressionBenchmark.main       bench/resources/go_suite/base64_byte_array.jsonnet  avgt        1.499          ms/op
125] RegressionBenchmark.main              bench/resources/go_suite/comparison.jsonnet  avgt       23.194          ms/op
125] RegressionBenchmark.main             bench/resources/go_suite/comparison2.jsonnet  avgt       77.113          ms/op
125] RegressionBenchmark.main        bench/resources/go_suite/escapeStringJson.jsonnet  avgt        0.051          ms/op
125] RegressionBenchmark.main                   bench/resources/go_suite/foldl.jsonnet  avgt        9.389          ms/op
125] RegressionBenchmark.main             bench/resources/go_suite/lstripChars.jsonnet  avgt        0.661          ms/op
125] RegressionBenchmark.main          bench/resources/go_suite/manifestJsonEx.jsonnet  avgt        0.071          ms/op
125] RegressionBenchmark.main          bench/resources/go_suite/manifestTomlEx.jsonnet  avgt        0.089          ms/op
125] RegressionBenchmark.main         bench/resources/go_suite/manifestYamlDoc.jsonnet  avgt        0.076          ms/op
125] RegressionBenchmark.main                  bench/resources/go_suite/member.jsonnet  avgt        0.734          ms/op
125] RegressionBenchmark.main                bench/resources/go_suite/parseInt.jsonnet  avgt        0.053          ms/op
125] RegressionBenchmark.main                 bench/resources/go_suite/reverse.jsonnet  avgt       10.990          ms/op
125] RegressionBenchmark.main             bench/resources/go_suite/rstripChars.jsonnet  avgt        0.649          ms/op
125] RegressionBenchmark.main              bench/resources/go_suite/stripChars.jsonnet  avgt        0.630          ms/op
125] RegressionBenchmark.main                  bench/resources/go_suite/substr.jsonnet  avgt        0.163          ms/op
125/125, SUCCESS] ./mill bench.runRegressions 399s

Copilot AI review requested due to automatic review settings March 1, 2026 15:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors Materializer.apply0 to avoid recursive JVM stack growth when materializing deeply nested objects/arrays, aiming to reduce StackOverflow risk by using an explicit stack.

Changes:

  • Replaced recursive object/array materialization with an iterative, stack-based algorithm.
  • Added materializeLeaf helper and stack frame types for object/array traversal.
  • Added documentation about a supposed TCO boundary and a defensive TailCall check.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@He-Pin He-Pin marked this pull request as draft March 1, 2026 15:06
@He-Pin He-Pin force-pushed the materializer branch 8 times, most recently from a231a79 to 43bf62b Compare March 1, 2026 18:19
@He-Pin He-Pin marked this pull request as ready for review March 1, 2026 19:08
@He-Pin He-Pin marked this pull request as draft March 1, 2026 19:08
@He-Pin He-Pin requested a review from Copilot March 2, 2026 02:33
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

sjsonnet/src/sjsonnet/Materializer.scala:22

  • Materializer now introduces a new abstract method storePos(v: Val). Because Materializer is a public abstract class, adding an abstract member is a source/binary breaking change for any downstream code that subclasses it. Consider making storePos(v: Val) a concrete (non-abstract) helper that delegates to storePos(v.pos) (or a default no-op) so existing subclasses continue to compile unchanged.
abstract class Materializer {
  def storePos(pos: Position): Unit
  def storePos(v: Val): Unit


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants