xiangfu0 opened a new pull request, #19514:
URL: https://github.com/apache/pinot/pull/19514

   Timestamp range predicates such as `event_time >= CAST('2024-01-01 00:00:00' 
AS TIMESTAMP)` compile a generated Java reducer for each constant cast during 
Calcite field trimming. Numeric epoch strings also pay this cost even though 
Calcite cannot parse them and leaves the casts for later Pinot planning.
   
   Add a narrow executor for ordinary CHAR/VARCHAR literal-to-TIMESTAMP casts. 
It calls the same Avatica parser and RexBuilder literal construction as 
Calcite's generated code. Unsupported expression batches still delegate to 
Calcite; a failed supported batch remains entirely unchanged. This preserves 
nulls, precision, invalid-input behavior and batch ordering.
   
   Install the executor only during SQL-to-rel conversion, restoring the prior 
executor before optimization and preserving explicitly supplied executors. 
Installing it only in a RelBuilder context is insufficient because 
`RelBuilder.transform` discards that context.
   
   ### Benchmark
   
   Independently packaged baseline `c6116095f7d3834613649c770d75fed7dd5a874a` 
and this change, with identical benchmark source and bytecode. The benchmark 
calls `QueryEnvironment.compile` and closes each compiled query, covering SQL 
parsing, validation, SQL-to-rel conversion and logical optimization. It cycles 
through 1,024 prebuilt synthetic account IDs. The measured window query filters 
a timestamp range and selects the latest event version using `ROW_NUMBER()`.
   
   Warmed results on a shared Apple M4 Pro host with 24 GiB RAM, OpenJDK 
25.0.4, JMH 1.37, one benchmark thread, 1 GiB heap and `ActiveProcessorCount=4`:
   
   | Window-query constant form | Baseline µs/op | PR µs/op | Latency change | 
Baseline B/op | PR B/op | Allocation change |
   |---|---:|---:|---:|---:|---:|---:|
   | Timestamp-string CAST | 1,327.98 | 483.56 | **−63.59%** | 1,332,499 | 
860,004 | **−35.46%** |
   | Epoch-string CAST | 1,314.98 | 506.25 | **−61.50%** | 1,335,453 | 864,977 
| **−35.23%** |
   | Typed TIMESTAMP literal control | 469.26 | 478.46 | +1.96% | 846,269 | 
846,059 | −0.02% |
   
   Each revision has two independent JVM forks, run baseline/PR/PR/baseline. 
Each fork uses five 3-second warmups and five 2-second measurements with the GC 
profiler. Means include every measured iteration. The control's direction 
reverses between pairs; one baseline control iteration is elevated and 
retained. These shared-host measurements establish a compilation benefit for 
these queries, not end-to-end query throughput or precise bounds on small 
regressions. Shorter pilot runs were excluded because they were still warming 
up.
   
   <details>
   <summary>Independent fork means and reproduction</summary>
   
   | Constant form | Baseline A/B µs/op | PR A/B µs/op |
   |---|---|---|
   | Timestamp-string CAST | 1,312.65 / 1,343.30 | 486.42 / 480.70 |
   | Epoch-string CAST | 1,329.88 / 1,300.09 | 496.79 / 515.71 |
   | Typed literal control | 452.94 / 485.58 | 486.35 / 470.58 |
   
   Copy `BenchmarkConstantCastPlanning.java` to a worktree at the baseline 
commit. Build each worktree separately with JDK 25:
   
   ```sh
   ./mvnw -pl pinot-perf -am package -Ppinot-fastdev -DskipTests \
     -Dskip.npm -Dskip.installnodenpm -Dcheckstyle.skip -Dspotless.check.skip \
     -Dlicense.skip -Denforcer.skip -Dshade.phase.prop=none \
     -Dassembly.skipAssembly=true -Dmaven.javadoc.skip=true
   ```
   
   Run the following once in each worktree in baseline/PR/PR/baseline order, 
without concurrent builds. Use distinct result filenames for each run. Verify 
the packaged planner and benchmark jars match their module target jars before 
running.
   
   ```sh
   "$JAVA_HOME/bin/java" -Xmx1g \
     -cp 'pinot-perf/target/pinot-perf-pkg/lib/*' org.openjdk.jmh.Main \
     BenchmarkConstantCastPlanning \
     -p _queryShape=WINDOW \
     -p _literalForm=CAST,EPOCH_STRING_CAST,TIMESTAMP_LITERAL \
     -wi 5 -w 3s -i 5 -r 2s -f 1 -t 1 -foe true -prof gc \
     -jvmArgs '-Xms1g -Xmx1g -XX:ActiveProcessorCount=4' \
     -rf json -rff result.json
   ```
   
   The harness also includes a simple FILTER query and a LONG epoch-millis 
column control for additional experiments.
   
   </details>
   
   Separate matched JFR runs corroborate the mechanism: Janino occurs in 
142/471 baseline JMH-worker execution samples and 0/750 PR samples. Sampling 
alone does not establish absence; the integration tests independently count 
generated reductions exactly.
   
   ### Validation
   
   - **900 planner tests passed:** 50 executor cases, 8 full-compilation cases, 
240 query-compilation cases, 10 type-coercion cases and 592 resource-based 
query plans.
   - The new full-compilation tests compare plans, row types and table names 
with typed timestamp literals, assert zero generated reducers, and verify the 
planner executor is restored. The baseline produces two generated reducers for 
the same queries while preserving plan equivalence.
   - Differential executor tests cover nulls, fractional precision/rounding, 
pre-epoch values, whitespace, invalid input, unsupported/mixed batches, custom 
executors and concurrent calls.
   - Spotless, Checkstyle and license checks pass for both changed modules. 
Direct JDK 25 lint compilation of all five changed sources has zero added-line 
warnings.
   - The stricter deprecation-enabled reactor check encounters an existing 
issue in unchanged `ZstandardDecompressor.java:51`: Zstd's provided JetBrains 
annotation dependency is absent from that module's compile classpath. This is 
reproduced on the identical baseline source; adding the annotation jar resolves 
that check. No unrelated dependency change is included here.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to