--- a/crates/jrsonnet-ir-parser/src/lib.rs +++ b/crates/jrsonnet-ir-parser/src/lib.rs @@ -304,10 +304,10 @@ None }; let step = if p.try_eat(T![:]) { - if !p.at(T![']']) { + if p.at(T![']']) { + None + } else { Some(spanned(p, expr)?) - } else { - None } } else { None --- a/nix/benchmarks.nix +++ b/nix/benchmarks.nix @@ -13,134 +13,149 @@ quick ? false, jrsonnetVariants, }: -with lib; let - jsonnetBench = fetchFromGitHub { - rev = "v0.19.1"; - owner = "google"; - repo = "jsonnet"; - hash = "sha256-q1MNdbyrx4vvN5woe0o90pPqaNtsZjI5RQ7KJt7rOpU="; - }; - goJsonnetBench = - (fetchFromGitHub { - owner = "google"; - repo = "go-jsonnet"; - rev = "v0.19.1"; - hash = "sha256-FgQYnas0qkIedRAA8ApZXLzEylg6PS6+8zzl7j+yOeI="; - }) - + "/builtin-benchmarks"; +with lib; +let + inherit (cpp-jsonnet) jsonnetBench; + inherit (go-jsonnet) goJsonnetBench; graalvmBench = fetchFromGitHub { owner = "oracle"; repo = "graal"; rev = "bc305df3fe587960f7635f0185571500e5988475"; hash = "sha256-4EKB1b2o4/qtYQ+nqbbs621OJrtjApsAWEBcw5EjrYc="; }; - kubePrometheusBench = let - src = fetchFromGitHub { - owner = "prometheus-operator"; - repo = "kube-prometheus"; - rev = "d3889807798d1697ea0691f10caf1b6a1997a8bd"; - hash = "sha256-TeYWHzoZAmDp2PzT7EH8XRUcvb3tR8Qfxel7o2QBvIM="; - }; - in + kubePrometheusBench = + let + src = fetchFromGitHub { + owner = "prometheus-operator"; + repo = "kube-prometheus"; + rev = "d3889807798d1697ea0691f10caf1b6a1997a8bd"; + hash = "sha256-TeYWHzoZAmDp2PzT7EH8XRUcvb3tR8Qfxel7o2QBvIM="; + }; + in runCommand "kube-prometheus-vendor" - { - outputHash = "sha256-AGc0dHlD/Ld7I5b1+gOotzJkYrn+bB1VjISdD5NITtw="; - outputHashMode = "recursive"; - buildInputs = [cacert]; - } - '' - mkdir -p $out - cp -r ${src}/* $out/ - cd $out - chmod u+w jsonnetfile.lock.json - mkdir vendor - ${jsonnet-bundler}/bin/jb install - ''; + { + outputHash = "sha256-AGc0dHlD/Ld7I5b1+gOotzJkYrn+bB1VjISdD5NITtw="; + outputHashMode = "recursive"; + buildInputs = [ cacert ]; + } + '' + mkdir -p $out + cp -r ${src}/* $out/ + cd $out + chmod u+w jsonnetfile.lock.json + mkdir vendor + ${jsonnet-bundler}/bin/jb install + ''; # Removes outsiders from the output # Useful when comparing performance of different jrsonnet releases - skipSlow = - if quick - then "slow benchmark, but only quick requested" - else ""; + skipSlow = if quick then "slow benchmark, but only quick requested" else ""; in - stdenv.mkDerivation { - name = "benchmarks"; - __impure = true; - unpackPhase = "true"; +stdenv.mkDerivation { + name = "benchmarks"; + __impure = true; + unpackPhase = "true"; - buildInputs = [ - sjsonnet - cpp-jsonnet - rsjsonnet - go-jsonnet + buildInputs = [ + sjsonnet + cpp-jsonnet + rsjsonnet + go-jsonnet - hyperfine - ]; + hyperfine + ]; - installPhase = let - mkBench = { - name, - path, - omitSource ? false, - pathIsGenerator ? false, - skipRustAlternative ? "", - skipScala ? "", - skipCpp ? "", - skipGo ? "", - vendor ? "", - }: '' - echo >> $out - echo "### ${name}" >> $out - echo >> $out - ${optionalString (skipRustAlternative != "") '' - echo "> Note: No results for Rust (alternative), ${skipRustAlternative}" >> $out - echo >> $out - ''} - ${optionalString (skipGo != "") '' - echo "> Note: No results for Go, ${skipGo}" >> $out - echo >> $out - ''} - ${optionalString (skipScala != "") '' - echo "> Note: No results for Scala, ${skipScala}" >> $out - echo >> $out - ''} - ${optionalString (skipCpp != "") '' - echo "> Note: No results for C++, ${skipCpp}" >> $out - echo >> $out - ''} - ${optionalString (!quick && !omitSource) '' - echo "
" >> $out - echo "Source" >> $out - echo >> $out - echo "\`\`\`jsonnet" >> $out - ${optionalString pathIsGenerator "echo \"// Generator source\" >> $out"} - cat ${path} >> $out + installPhase = + let + mkBench = + { + name, + path, + omitSource ? false, + pathIsGenerator ? false, + skipRustAlternative ? "", + skipScala ? "", + skipCpp ? "", + skipGo ? "", + vendor ? "", + }: + '' echo >> $out - echo "\`\`\`" >> $out - echo "
" >> $out + echo "### ${name}" >> $out echo >> $out - ''} - path=${path} - ${optionalString pathIsGenerator '' - go-jsonnet $path > generated.jsonnet - path=generated.jsonnet - ''} - hyperfine -N -w4 -m20 --output=pipe --style=basic --export-asciidoc result.adoc \ - ${concatStringsSep " " (forEach jrsonnetVariants ( - variant: "\"${variant.drv}/bin/jrsonnet $path${optionalString (vendor != "") " -J${vendor}"}\" -n \"Rust${ - if variant.name != "" - then " (${variant.name})" - else "" - }\"" - ))} \ - ${optionalString (skipRustAlternative == "") "\"rsjsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Rust (alternative, rsjsonnet)\""} \ - ${optionalString (skipGo == "") "\"go-jsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Go\""} \ - ${optionalString (skipScala == "") "\"sjsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Scala\""} \ - ${optionalString (skipCpp == "") "\"jsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"C++\""} - cat result.adoc >> $out - ''; - in '' + ${optionalString (skipRustAlternative != "") '' + echo "> Note: No results for Rust (alternative), ${skipRustAlternative}" >> $out + echo >> $out + ''} + ${optionalString (skipGo != "") '' + echo "> Note: No results for Go, ${skipGo}" >> $out + echo >> $out + ''} + ${optionalString (skipScala != "") '' + echo "> Note: No results for Scala/Scala (native)/Scala (GraalVM), ${skipScala}" >> $out + echo >> $out + ''} + ${optionalString (skipCpp != "") '' + echo "> Note: No results for C++, ${skipCpp}" >> $out + echo >> $out + ''} + ${optionalString (!quick && !omitSource) '' + echo "
" >> $out + echo "Source" >> $out + echo >> $out + echo "\`\`\`jsonnet" >> $out + ${optionalString pathIsGenerator "echo \"// Generator source\" >> $out"} + cat ${path} >> $out + echo >> $out + echo "\`\`\`" >> $out + echo "
" >> $out + echo >> $out + ''} + path=${path} + ${optionalString pathIsGenerator '' + go-jsonnet $path > generated.jsonnet + path=generated.jsonnet + ''} + hyperfine -N -w4 -m20 --output=pipe --style=basic --export-asciidoc result.adoc \ + ${ + concatStringsSep " " ( + forEach jrsonnetVariants ( + variant: + "\"${variant.drv}/bin/jrsonnet $path${optionalString (vendor != "") " -J${vendor}"}\" -n \"Rust${ + if variant.name != "" then " (${variant.name})" else "" + }\"" + ) + ) + } \ + ${ + optionalString (skipRustAlternative == "") + "\"rsjsonnet $path${ + optionalString (vendor != "") " -J ${vendor}" + }\" -n \"Rust (alternative, rsjsonnet)\"" + } \ + ${ + optionalString (skipGo == "") + "\"go-jsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Go\"" + } \ + ${ + optionalString (skipScala == "") + "\"sjsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Scala\"" + } \ + ${ + optionalString (skipScala == "") + "\"sjsonnet-native $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Scala (native)\"" + } \ + ${ + optionalString (skipScala == "") + "\"sjsonnet-graalvm $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Scala (GraalVM)\"" + } \ + ${optionalString (skipCpp == "") + "\"jsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"C++\"" + } + cat result.adoc >> $out + ''; + in + '' set -oux temp=$(mktemp -d) @@ -172,6 +187,18 @@ sjsonnet 2>> $out || true echo "\`\`\`" >> $out echo >> $out + echo "Scala (native):" >> $out + echo >> $out + echo "\`\`\`" >> $out + sjsonnet-native 2>> $out || true + echo "\`\`\`" >> $out + echo >> $out + echo "Scala (GraalVM):" >> $out + echo >> $out + echo "\`\`\`" >> $out + sjsonnet-graalvm 2>> $out || true + echo "\`\`\`" >> $out + echo >> $out echo "Rust (alternative):" >> $out echo >> $out echo "\`\`\`" >> $out @@ -187,6 +214,7 @@ ${mkBench { name = "Graalvm CI"; path = "${graalvmBench}/ci.jsonnet"; + omitSource = true; skipCpp = "takes longer than a hour"; skipGo = skipSlow; skipScala = skipSlow; @@ -195,7 +223,8 @@ name = "Kube-prometheus manifests"; vendor = "${kubePrometheusBench}/vendor"; path = "${kubePrometheusBench}/example.jsonnet"; - skipCpp = skipSlow; + omitSource = true; + skipCpp = "too slow, takes hours, skews results"; skipGo = skipSlow; skipScala = skipSlow; }} @@ -212,21 +241,21 @@ omitSource = true; path = "${jsonnetBench}/perf_tests/large_string_template.jsonnet"; skipGo = "fails with os stack size exhausion"; - skipCpp = skipSlow; + skipCpp = "too slow, takes hours, skews results"; skipScala = skipSlow; }} ${mkBench { name = "Realistic 1"; path = "${jsonnetBench}/perf_tests/realistic1.jsonnet"; skipGo = skipSlow; - skipCpp = skipSlow; + skipCpp = "too slow, takes hours, skews results"; skipScala = skipSlow; }} ${mkBench { name = "Realistic 2"; path = "${jsonnetBench}/perf_tests/realistic2.jsonnet"; skipGo = skipSlow; - skipCpp = skipSlow; + skipCpp = "too slow, takes hours, skews results"; skipScala = skipSlow; }} @@ -259,8 +288,6 @@ name = "Array sorts"; path = "${jsonnetBench}/benchmarks/bench.06.jsonnet"; skipCpp = skipSlow; - # std.assertEqual(reverse(std.range(1, 1000)), sort(std.range(1, 1000), keyF=function(x) -x)) - skipScala = "sjsonnet doesn't support keyF in std.sort: https://github.com/databricks/sjsonnet/issues/204"; }} ${mkBench { name = "Lazy array"; @@ -277,7 +304,7 @@ ${mkBench { name = "String strips"; path = "${jsonnetBench}/benchmarks/bench.09.jsonnet"; - skipCpp = skipSlow; + skipCpp = "too slow, takes hours, skews results"; skipScala = skipSlow; }} ${mkBench { @@ -293,7 +320,7 @@ name = "std.base64"; path = "${goJsonnetBench}/base64.jsonnet"; skipRustAlternative = skipSlow; - skipCpp = skipSlow; + skipCpp = "too slow, takes hours, skews results"; skipScala = skipSlow; }} ${mkBench { @@ -333,7 +360,6 @@ ${mkBench { name = "std.manifestTomlEx"; path = "${goJsonnetBench}/manifestTomlEx.jsonnet"; - skipScala = "std.manifestTomlEx is not implemented: https://github.com/databricks/sjsonnet/issues/111"; skipCpp = skipSlow; }} ${mkBench { @@ -356,8 +382,7 @@ ${mkBench { name = "Comparsion for array"; path = "${goJsonnetBench}/comparison.jsonnet"; - skipScala = "array comparsion is not implemented"; - skipCpp = skipSlow; + skipCpp = "too slow, takes hours, skews results"; }} ${mkBench { name = "Comparsion for primitives"; @@ -368,4 +393,4 @@ skipScala = skipSlow; }} ''; - } +} --- a/nix/cpp-jsonnet.nix +++ b/nix/cpp-jsonnet.nix @@ -5,12 +5,12 @@ }: let pname = "cpp-jsonnet"; - version = "0.21.0"; + version = "2026-03-23"; src = fetchFromGitHub { - rev = "v${version}"; + rev = "d33798d495d50df427dac0dc6934220e366976fb"; owner = "google"; repo = "jsonnet"; - hash = "sha256-QHp0DOu/pqcgN7di219cHzfFb7fWtdGGE6J1ZXgbOGQ="; + hash = "sha256-fpXaYK6WKpXQ0/VbHHsE8ZR/0VpJHmFul/3a6HzBa5o="; }; in stdenv.mkDerivation { @@ -28,5 +28,8 @@ wrapProgram $out/bin/jsonnet --add-flags "--max-stack 200000" ''; - passthru = { inherit src; }; + passthru = { + inherit src; + jsonnetBench = src; + }; } --- a/nix/go-jsonnet.nix +++ b/nix/go-jsonnet.nix @@ -5,18 +5,18 @@ }: let pname = "go-jsonnet"; - version = "0.21.0"; + version = "2026-03-23"; src = fetchFromGitHub { owner = "google"; repo = pname; - rev = "v${version}"; - hash = "sha256-J92xNDpCidbiSsN6NveS6BX6Tx+qDQqkgm6pjk1wBTQ="; + rev = "b5ef4cd9c4e24f2f14a68ef3bda0ca3079e11e78"; + hash = "sha256-htC8671r74E26J42eubcFL4lPOURIdSK0P7GjZOWhao="; }; in buildGoModule { inherit pname version src; - vendorHash = "sha256-Uh2rAXdye9QmmZuEqx1qeokE9Z9domyHsSFlU7YZsZw="; + vendorHash = "sha256-uFCvMmiZVaRYhaORI92W0pkDjDZNiWIcop70FssJiZo="; buildInputs = [ makeWrapper ]; @@ -25,7 +25,10 @@ wrapProgram $out/bin/go-jsonnet --add-flags "--max-stack 200000" ''; - passthru = { inherit src; }; + passthru = { + inherit src; + goJsonnetBench = src + "/builtin-benchmarks"; + }; doCheck = false; --- a/nix/rsjsonnet.nix +++ b/nix/rsjsonnet.nix @@ -5,16 +5,16 @@ }: rustPlatform.buildRustPackage rec { pname = "rsjsonnet"; - version = "0.4.0"; + version = "2026-03-23"; src = fetchFromGitHub { owner = "eduardosm"; repo = pname; - rev = "v${version}"; - hash = "sha256-Oas/fll5YerHAMI91fTEQqe6praYh4Ro8idsdvzldpA="; + rev = "27be31532180c611383ceb2b7f03193ab1253487"; + hash = "sha256-0VM6v1VfQOGUXuYOuh90ta1GaLf1YA+Apm3SkH8CDN4="; }; - cargoHash = "sha256-jH2BOvD0Iss34hODhLFHKx5pGMVtkZir7E1bYwjSa8E="; + cargoHash = "sha256-0IDAxm4J2rEqfUGNYoQTP0RPrEZe4YPe2E6TT7A4THo="; nativeBuildInputs = [makeWrapper]; --- a/nix/sjsonnet.nix +++ b/nix/sjsonnet.nix @@ -4,27 +4,71 @@ # TODO: Somehow build client-server version of sjsonnet, and use it in benchmarks { stdenv, + lib, fetchurl, jdk25_headless, makeWrapper, + autoPatchelfHook, + zlib, + openssl, java ? jdk25_headless, }: -stdenv.mkDerivation rec { +let + version = "0.6.2"; + baseUrl = "https://github.com/databricks/sjsonnet/releases/download/${version}"; + + nativePlatform = { + x86_64-linux = "linux-x86_64"; + aarch64-linux = "linux-arm64"; + aarch64-darwin = "darwin-arm64"; + # Nobody cares about darwin on intel + }.${stdenv.hostPlatform.system} or (throw "unsupported system: ${stdenv.hostPlatform.system}"); + + nativeSrc = fetchurl { + url = "${baseUrl}/sjsonnet-${version}-${nativePlatform}"; + hash = { + x86_64-linux = "sha256-r79Q6SovcPIomDDUYTGIP35/y5t9Xo5Z3ohP7pxsF8I="; + aarch64-linux = "sha256-LxWR94u1Oncau57Kmtzj2UFEofWGT4+laDTbRDkwv08="; + aarch64-darwin = "sha256-gNZ6XekMm+ebeD7UFeRfoapXw/90gHk8MoeGD86dzKk="; + }.${stdenv.hostPlatform.system}; + }; + + graalvmSrc = fetchurl { + url = "${baseUrl}/sjsonnet-graalvm-${version}-${nativePlatform}"; + hash = { + x86_64-linux = "sha256-XNJCnQlwVFySrUevn1nLN/DY8UBGgvCFAitkedLB+yM="; + aarch64-linux = "sha256-J+C3pmiBEmo8M00IDHp9jznonibXmHVRlhsvQ4apVWw="; + aarch64-darwin = "sha256-TXNL52sS4NE3GjbOFtgf6aCP268qGKMFaoTwAfJfgGc="; + }.${stdenv.hostPlatform.system}; + }; +in +stdenv.mkDerivation { pname = "sjsonnet"; - version = "0.6.0"; + inherit version; src = fetchurl { - url = "https://github.com/databricks/${pname}/releases/download/${version}/${pname}-${version}.jar"; - hash = "sha256-HQovfF/hX664apg9Pl9SdrK03b8rmZ9IjHpf7uNY8FM="; + url = "${baseUrl}/sjsonnet-${version}.jar"; + hash = "sha256-jvkrxY48d/UdMGRoB9SxCJU2JJirfhZNyNMSkMrrQ7w="; }; unpackPhase = "true"; - buildInputs = [java makeWrapper]; + nativeBuildInputs = [ makeWrapper ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ]; + buildInputs = [ java ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ zlib openssl stdenv.cc.cc.lib ]; installPhase = '' mkdir -p $out/bin $out/lib cp $src $out/lib/sjsonnet.jar makeWrapper ${java}/bin/java $out/bin/sjsonnet --add-flags "-Xss100m -XX:+UseStringDeduplication -jar $out/lib/sjsonnet.jar" + + cp ${nativeSrc} $out/bin/sjsonnet-native + chmod +x $out/bin/sjsonnet-native + wrapProgram $out/bin/sjsonnet-native --add-flags "--max-stack 200000" + + cp ${graalvmSrc} $out/bin/sjsonnet-graalvm + chmod +x $out/bin/sjsonnet-graalvm + wrapProgram $out/bin/sjsonnet-graalvm --add-flags "--max-stack 200000" ''; separateDebugInfo = false; }