databird07 opened a new pull request, #20364:
URL: https://github.com/apache/hudi/pull/20364
### Describe the issue this Pull Request addresses
- Java CI on master (`bot.yml` + `java_ci_engines.yml`) uses about 680
runner job-minutes per push, counted as the sum of every job's duration.
- This PR cuts that total without dropping test areas or coverage.
- Whole workflow, every job counted: **682.1 → 484.3 job-minutes (−29%)**.
Master runs 40306329236 + 40306329230, PR runs 40374455400 + 40374455419.
- On the jobs this PR changes (all test jobs, plus its shared builds):
**550.1 → 348.6 (−37%)**.
- Bundle validation and integration-tests are unchanged by this PR and take
about 130 job-minutes on both sides.
### Summary and Changelog
**The total falls because each job does less work, not because the work is
spread over more jobs.**
- Job-minutes add up every job's duration. Splitting a job into more jobs
would leave the total unchanged.
- Most of the saving removes work: builds that ran twice, tests that ran
twice, sleeps, process forks, allocations and redundant matrix rows.
- One change is parallelism: two surefire JVMs on the same runner, using
cores that were idle. The runner is billed until the job ends, so a shorter job
uses fewer job-minutes. This was dropped for hudi-utilities, where it made the
job slower.
**Duplicate work removed**
- Build once: 3 shared build jobs upload `target/` and the Hudi `.m2`
artifacts. The test jobs restore them instead of each running `mvn clean
install -DskipTests`. The restore checks a manifest of the commit and profile
set.
- The JDK 11 artifact leaves out what its `mvn test` jobs never read: shaded
bundle jars (except `hudi-utilities-bundle`, which hudi-cli resolves from
`.m2`), the `hudi-examples-k8s` jar and `-sources.jar` files. 3.92 GB → 1.18
GB; restore time across its 4 jobs went from 59–95 to 17 job-minutes.
- `test-flink-2`: `-Dit.test=!ITTestHoodieDataSource` matched every class,
so the job also re-ran all 183 hudi-flink unit-test classes. Those already run
in `test-common-and-other-modules`. The filter is now
`IT*,!ITTestHoodieDataSource`; the job went from 42.7 to 14.0 min.
**Waiting removed**
- Test configs set `max_expected_clock_skew_ms=1` instead of 200 ms, in the
Flink tests and `HoodieSparkSqlTestBase`. That sleep runs on every instant
generated under a lock.
- ITTestDataStreamWrite checkpoints every 1 s instead of 4 s, and two
`sleep(2)` calls are gone.
- Heartbeat-expiry tests backdate the heartbeat file instead of sleeping
about 30 s.
- The streamer clustering-conflict retry is configurable:
`--clustering-conflict-retry-interval-seconds`, default 60 s as before. The
conflict test uses 2 s.
- TestWriterWithPartitionTTl now waits out its 1 s TTL explicitly. It used
to depend on the 200 ms sleeps adding up.
**Per-operation overhead removed**
- `NioPermissionLocalFileSystem` (test-only) sets file permissions through
`java.nio`. Without Hadoop native IO, as on CI, Hadoop starts a `chmod` process
per file; hudi-spark tests went from about 23k of those to 0. It is wired into
the utilities, Spark client and Scala SQL test bases.
- HFile whole-file reads use a `min(fileSize, defaultBufferSize)` buffer
instead of allocating 32 MB on every open (production code).
- `HadoopStorageConfiguration` Java serialization writes plain key/value
pairs instead of `Configuration#write`, which gzips every property's source
list (production code). Serialize and deserialize are 7–30x faster. Payloads in
the old format (e.g. Flink state from an older Hudi) are still read through
`Configuration#readFields`.
**Redundant test cases removed** (the full matrix still runs on the current
table version; v6 rows are kept)
- Older-version rows (v8/v9) were trimmed in TestMORDataSource,
TestColumnStatsIndex, the merge-mode SQL suites, and the
TestHoodieDeltaStreamer and SchemaEvolutionQuick matrices (pairwise).
- TestHoodieFileSystemViews runs MDT-on only, and each table is written once
for both view types.
- Read-only cases share one table fixture in TestColumnStatsIndexWithSQL and
TestHoodieMetadataTableValidator.
- TestBootstrapIndex runs 10 validations per thread instead of 50, still
with 20 concurrent threads.
**Fixes found along the way**
- KafkaTestUtils now waits for partition leaders and checks send acks. Lost
records used to cause a flaky 120 s timeout that reruns hid.
- TestColumnStatsIndexWithSQL now really writes v6/8/9 tables. It never
passed `tableVersion` to the writer before.
- RLI lookup-metrics tests shut down all live `Metrics` before clearing the
shared capturing reporter. A reporter left attached by an earlier test made
them flaky (also on master).
- `spark.ui.enable` is corrected to `spark.ui.enabled` in UtilitiesTestBase.
**Measured per job** (master runs 40306329236 + 40306329230 → PR runs
40374455400 + 40374455419, in minutes)
- Java part1 65.5 → 42.4, part2 70.3 → 42.1, part3 36.1 → 25.9
- Scala DML 62.3 → 29.6, Scala other 72.7 → 25.1
- Flink 1 34.4 → 24.2, Flink 2 39.5 → 14.2
- utilities 51.7 → 35.5, common + other modules 63.2 → 44.6
- spark-client + hadoop-common 39.8 → 34.9, hadoop-mr + java-client 14.6 →
9.6
- The three shared builds add 20.5.
- Not changed by this PR: bundle validation 96.2 → 99.4, integration-tests
35.8 → 36.2.
- Single-run job times vary by about 7–15 min per job.
**How it was verified**
- Each change was timed locally in 6–20 alternating before/after runs with
JaCoCo on, with the same test counts and 0 failures. Results are in each commit
message.
- JaCoCo diffs found no lost lines, apart from a few timing-dependent ones
that other tests still cover. Codecov on an earlier run went from 80.73% to
80.74%.
- Every changed production line in `HadoopStorageConfiguration` is covered
by `TestHadoopStorageConfiguration`, including the old-format and
unknown-version paths.
- The branch is rebased onto master c0ed52483f. The new build jobs use
`ubuntu-24.04`, matching master's runner pin (#20418). The workflow changes
were moved into the split `bot.yml` and `java_ci_engines.yml`. `build-flink`
lives in `java_ci_engines.yml`, because artifacts only download within the same
workflow run.
### Impact
- Mostly CI and test code. There are three production changes:
- The HFile read buffer size.
- The `HadoopStorageConfiguration` serialization format. Older payloads
still deserialize. An older Hudi reading the new format gets an empty
`Configuration` without any error. So mixing Hudi versions between driver and
executors, or downgrading a Flink job onto new state, isn't supported.
- The new streamer option, whose default keeps the old behaviour.
- One deliberate coverage tradeoff: no Spark-record StreamSync write to a v8
table. v8 still runs with Avro records.
- MDT-off file-system-view cases were removed. Those writer paths stay
covered by `TestHoodieBackedMetadata` and `TestHoodieTableFileSystemView`.
### Risk Level
medium
- Two surefire JVMs can expose shared-resource assumptions. Ports are per
fork, and the change was checked with 4 full-job runs and 60 repeated subset
runs in random order.
- Build once depends on restored outputs being treated as up to date.
Manifests are checked and mtimes are re-stamped.
- Each change is its own commit and can be reverted on its own.
### Documentation Update
none
### Contributor's checklist
- [x] Read through [contributor's
guide](https://hudi.apache.org/contribute/how-to-contribute)
- [x] Enough context is provided in the sections above
- [x] Adequate tests were added if applicable
--
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]