This is an automated email from the ASF dual-hosted git repository.

LuciferYang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 5fd608b82509 [SPARK-57411][INFRA] Add a daily build with the JDK 
codegen backend
5fd608b82509 is described below

commit 5fd608b825090e9da3b06107dc0756d114fb815b
Author: YangJie <[email protected]>
AuthorDate: Tue Aug 18 20:57:17 2026 +0800

    [SPARK-57411][INFRA] Add a daily build with the JDK codegen backend
    
    ### What changes were proposed in this pull request?
    
    Adds `build_codegen_jdk.yml`, a scheduled workflow that runs the test suite 
with `spark.sql.codegen.compiler=jdk` every other day. The change has two parts:
    
    - `SPARK_CODEGEN_COMPILER` overrides the `spark.sql.codegen.compiler` 
default, so the workflow can select the backend through `envs`. This follows 
the shape `SPARK_ANSI_SQL_MODE` already uses for `spark.sql.ansi.enabled`, and 
the four TPC-DS steps forward the variable explicitly the same way they forward 
that one. An empty value counts as unset, for the reason in the testing section.
    - The workflow raises three job timeouts to 200, 130 and 140, because javac 
pushes those jobs past their defaults. The inputs it passes came from #58833, 
split out of this PR per review feedback and now merged. Numbers are in the 
testing section.
    
    The workflow keeps only the jobs that compile generated code: build, 
pyspark, pyspark-pandas, sparkr, tpcds-1g, docker-integration-tests, yarn. 
Docs, lint, buf and ui are skipped because they never reach 
`CodeGenerator.compile`. It runs on `*/2` days, matching the cadence of the 
other heavy scheduled builds; daily would have made a non-default backend 
roughly twice the compute of the next-heaviest scheduled workflow.
    
    ### Why are the changes needed?
    
    The default backend is Janino, so `CodeCompilerSuite` is currently the only 
suite that exercises `JdkCodeCompiler`. Every other generated unit could take 
the javac path and none of them is tested on it. The SPARK-57403 umbrella aims 
at `spark.sql.codegen.compiler=jdk` actually meaning javac, and there is no 
signal today on whether that holds beyond one suite.
    
    This has already cost us. The four silent-wrong-answer bugs fixed in #57768 
(a shadowed field, a hidden static method, an instance method clashing with a 
static, and an array type) were all found by hand-probing reflection semantics 
rather than by a failing test. Each sits on a path the encoder, 
`ObjectExpressions` and `Dataset` suites already cover under Janino, so running 
those suites on the JDK backend is what turns the next such bug into a test 
failure instead of a wrong query result.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. The config default is unchanged unless `SPARK_CODEGEN_COMPILER` is set 
to `janino` or `jdk`, which only the new workflow does.
    
    ### How was this patch tested?
    
    Three probe runs of the full suite on the JDK backend, driven by a branch 
commit that flipped the `build_and_test.yml` default `envs` to `jdk`. That 
commit is reverted here; it existed only to measure the cost and the failure 
count.
    
    The last of them, run 31593826890, was green across all 33 jobs: 79201 
tests, 0 failures. Every job outside `CodeCompilerSuite` passes on javac.
    
    Durations for the jobs that ran near their limit, javac against Janino:
    
    | job | javac | Janino | old cap | new cap |
    | --- | --- | --- | --- | --- |
    | `sql - other tests` | 171m | 127m | 150 | 200 |
    | `pyspark-sql` and the rest of its matrix entry | 109m | 73m | 120 | 130 |
    | `docker-integration-tests` | 116m | 102m | 120 | 140 |
    
    Each new cap is the javac figure plus about 20%. The Janino column is the 
slowest observed across recent runs of `build_main`, `build_java21`, 
`build_java25`, `build_non_ansi` and `build_uds`, five to twelve samples 
depending on the job. The 171m is a single measurement: the first two probe 
runs cancelled that job at the 150 default, which bounds it from below and says 
nothing more. Next closest after these three was `sql - slow tests` at 124m 
against a 150 cap, so it needed no change [...]
    
    On test failures, the first run reported 2 out of 76519, in 
`StateDataSourceTransformWithStateSuiteCheckpointV2`, on leaked file streams. 
Neither later run reproduced it, and that suite has failed before on a commit 
using the Janino default, so it is not a javac problem. Its logs have since 
expired, so run 31593826890 and its 0 failures is the part of this that can 
still be re-checked.
    
    Reverting the probe then turned up a bug in the env override itself, which 
is worth recording because it is the one place this change could have broken 
other callers. `tpcds-1g` failed with:
    
    ```
    [INVALID_CONF_VALUE.OUT_OF_RANGE_OF_OPTIONS] The value '' in the config
    "spark.sql.codegen.compiler" is invalid. It should be one of 'janino, jdk'.
    ```
    
    The TPC-DS steps read `${{ fromJSON(inputs.envs).SPARK_CODEGEN_COMPILER 
}}`, and only this PR's new workflow puts that key in its `envs`. For every 
other caller the expression resolves to nothing, and the runner exports the 
variable with an empty value rather than omitting it. `System.getenv` reports 
it as present with a zero-length string, so `getOrElse` returned `""` and 
`checkValues` rejected it on the first read of the config. The two existing 
env-driven confs in `SQLConf` avoid t [...]
    
    The conf now filters the empty string out, which keeps the variable's three 
states distinct: unset and empty both mean use the default, anything else is 
validated as before. Probed all of them against a forked JVM: unset gives 
janino, empty gives janino, `jdk` gives jdk, `JDK` gives jdk (the `transform` 
still lowercases), and `ecj` is still rejected. The empty case fails without 
the filter and passes with it.
    
    One coverage gap came out of the same review. The fourth TPC-DS step, "Run 
TPC-DS queries on collated data", had no `env:` block at all, so 
`TPCDSCollationQueryTestSuite` was still running on Janino inside this very 
workflow. It now gets the variable like the other three. That step also still 
lacks `SPARK_ANSI_SQL_MODE`, which `build_non_ansi.yml` would presumably want; 
left alone here as a separate question.
    
    Locally, `CodeCompilerSuite` passes (60 tests), along with 
`catalyst/compile` and `catalyst/scalastyle`. `CodeCompilerSuite` and 
`CodeGenerationSuite` also pass with the default flipped 
(`SPARK_CODEGEN_COMPILER=jdk build/sbt "catalyst/testOnly *CodeCompilerSuite 
*CodeGenerationSuite"`, 97 tests), which confirms no test depends on the 
default being `janino`.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 5
    
    Closes #57925 from LuciferYang/spark-codegen-jdk-daily.
    
    Authored-by: YangJie <[email protected]>
    Signed-off-by: yangjie01 <[email protected]>
---
 .github/workflows/build_and_test.yml               |  5 ++
 .github/workflows/build_codegen_jdk.yml            | 65 ++++++++++++++++++++++
 README.md                                          |  1 +
 .../org/apache/spark/sql/internal/SQLConf.scala    |  3 +-
 4 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/build_and_test.yml 
b/.github/workflows/build_and_test.yml
index 15b55bf9aa49..78dbfc5c2521 100644
--- a/.github/workflows/build_and_test.yml
+++ b/.github/workflows/build_and_test.yml
@@ -1348,6 +1348,7 @@ jobs:
         SPARK_TPCDS_DATA=`pwd`/tpcds-sf-1 build/sbt "sql/testOnly 
org.apache.spark.sql.TPCDSQueryTestSuite"
       env:
         SPARK_ANSI_SQL_MODE: ${{ fromJSON(inputs.envs).SPARK_ANSI_SQL_MODE }}
+        SPARK_CODEGEN_COMPILER: ${{ 
fromJSON(inputs.envs).SPARK_CODEGEN_COMPILER }}
         SPARK_TPCDS_JOIN_CONF: |
           spark.sql.autoBroadcastJoinThreshold=-1
           spark.sql.join.preferSortMergeJoin=true
@@ -1356,6 +1357,7 @@ jobs:
         SPARK_TPCDS_DATA=`pwd`/tpcds-sf-1 build/sbt "sql/testOnly 
org.apache.spark.sql.TPCDSQueryTestSuite"
       env:
         SPARK_ANSI_SQL_MODE: ${{ fromJSON(inputs.envs).SPARK_ANSI_SQL_MODE }}
+        SPARK_CODEGEN_COMPILER: ${{ 
fromJSON(inputs.envs).SPARK_CODEGEN_COMPILER }}
         SPARK_TPCDS_JOIN_CONF: |
           spark.sql.autoBroadcastJoinThreshold=10485760
     - name: Run TPC-DS queries (Shuffled hash join)
@@ -1363,12 +1365,15 @@ jobs:
         SPARK_TPCDS_DATA=`pwd`/tpcds-sf-1 build/sbt "sql/testOnly 
org.apache.spark.sql.TPCDSQueryTestSuite"
       env:
         SPARK_ANSI_SQL_MODE: ${{ fromJSON(inputs.envs).SPARK_ANSI_SQL_MODE }}
+        SPARK_CODEGEN_COMPILER: ${{ 
fromJSON(inputs.envs).SPARK_CODEGEN_COMPILER }}
         SPARK_TPCDS_JOIN_CONF: |
           spark.sql.autoBroadcastJoinThreshold=-1
           spark.sql.join.forceApplyShuffledHashJoin=true
     - name: Run TPC-DS queries on collated data
       run: |
         SPARK_TPCDS_DATA=`pwd`/tpcds-sf-1 build/sbt "sql/testOnly 
org.apache.spark.sql.TPCDSCollationQueryTestSuite"
+      env:
+        SPARK_CODEGEN_COMPILER: ${{ 
fromJSON(inputs.envs).SPARK_CODEGEN_COMPILER }}
     - name: Upload test results to report
       if: always()
       uses: actions/upload-artifact@v7
diff --git a/.github/workflows/build_codegen_jdk.yml 
b/.github/workflows/build_codegen_jdk.yml
new file mode 100644
index 000000000000..3df5f94ce484
--- /dev/null
+++ b/.github/workflows/build_codegen_jdk.yml
@@ -0,0 +1,65 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Runs the test suite with `spark.sql.codegen.compiler=jdk`, so that codegen
+# reaching the JDK backend is covered by more than `CodeCompilerSuite`. The
+# default backend is Janino, which leaves the javac path (SPARK-57403) 
exercised
+# only by its own suite even though every generated unit could take it.
+#
+# javac is slower than Janino, so this runs on its own schedule rather than on
+# every push, skips the jobs that do not compile generated code (docs, lint, 
buf,
+# ui), and raises the timeout of the three jobs that no longer fit their 
default.
+name: "Build / Codegen JDK backend (master, Scala 2.13, JDK 17)"
+
+on:
+  schedule:
+    - cron: '37 8 */2 * *'
+  workflow_dispatch:
+
+jobs:
+  run-build:
+    permissions:
+      packages: write
+    name: Run
+    uses: ./.github/workflows/build_and_test.yml
+    if: github.repository == 'apache/spark'
+    with:
+      java: 17
+      branch: master
+      hadoop: hadoop3
+      # See SPARK-57411 for the measurements behind these three.
+      build_timeout_minutes: 200
+      pyspark_timeout_minutes: 130
+      docker_integration_tests_timeout_minutes: 140
+      envs: >-
+        {
+          "PYSPARK_IMAGE_TO_TEST": "python-312",
+          "PYTHON_TO_TEST": "python3.12",
+          "SPARK_CODEGEN_COMPILER": "jdk"
+        }
+      jobs: >-
+        {
+          "build": "true",
+          "pyspark": "true",
+          "pyspark-pandas": "true",
+          "sparkr": "true",
+          "tpcds-1g": "true",
+          "docker-integration-tests": "true",
+          "yarn": "true"
+        }
diff --git a/README.md b/README.md
index a8349b9ba5e7..b57b53688f54 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,7 @@ This README file only contains basic setup instructions.
 |            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_java21.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_java21.yml)
                                     |
 |            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_java25.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_java25.yml)
                                     |
 |            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_non_ansi.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_non_ansi.yml)
                                 |
+|            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_codegen_jdk.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_codegen_jdk.yml)
                           |
 |            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_uds.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_uds.yml)
                                           |
 |            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_rockdb_as_ui_backend.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_rockdb_as_ui_backend.yml)
         |
 |            | [![GitHub Actions 
Build](https://github.com/apache/spark/actions/workflows/build_maven.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven.yml)
                                       |
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
index a10af15b2822..4deaa0bcf7f2 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
@@ -2984,7 +2984,8 @@ object SQLConf {
     .stringConf
     .transform(_.toLowerCase(Locale.ROOT))
     .checkValues(Set("janino", "jdk"))
-    .createWithDefault("janino")
+    .createWithDefault(
+      
sys.env.get("SPARK_CODEGEN_COMPILER").filter(_.nonEmpty).getOrElse("janino"))
 
   val WHOLESTAGE_HUGE_METHOD_LIMIT = 
buildConf("spark.sql.codegen.hugeMethodLimit")
     .internal()


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to