Skip to content

[GLUTEN][VL] Defer Delta deletion vector reads to executors - #12836

Open
malinjawi wants to merge 7 commits into
apache:mainfrom
malinjawi:agent/delta-dv-native-range-read
Open

[GLUTEN][VL] Defer Delta deletion vector reads to executors#12836
malinjawi wants to merge 7 commits into
apache:mainfrom
malinjawi:agent/delta-dv-native-range-read

Conversation

@malinjawi

@malinjawi malinjawi commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

What changes are proposed in this pull request?

Native Delta scans currently load every on-disk deletion vector while the driver builds file splits. With 2,461 S3-backed DVs, this kept executors idle for about two minutes before the first Spark job.

This PR passes each DV's absolute path, offset, size, and Hadoop configuration with the Spark partition, then loads the payload during executor-side split serialization.

  • On-disk DVs always load on executors; the serial driver-loading path is removed.
  • Reads use Delta's checksum-validating APIs.
  • Successful reads are memoized per task, and concurrent callers share one load.
  • Failed reads are not cached, so task retries can read again.
  • Metrics register after TaskContext becomes available.
  • Inline DVs remain eager because their bytes are already in Delta metadata.
  • The protobuf payload and native filtering are unchanged.

The production DV data-path change is confined to the JVM handoff. The PR also adds metrics, tests, documentation, and required CI baseline maintenance. spark.gluten.sql.columnar.filescan=false remains the broad fallback that disables native file scan. Direct Velox range reads are handled separately in #12867.

How was this patch tested?

  • Scala formatting, generated configuration documentation, configuration suites, and git diff --check.
  • Test-source compilation for Spark 3.3 / Delta 2.3, Spark 3.5 / Delta 3.3, and Spark 4.0 / Delta 4.0.
  • Shared Delta 3.3/4.0 tests for serialization, executor materialization, concurrent single-read memoization, failed-read retry, and eager inline DVs without filesystem access.
  • Version-specific native handoff tests assert executor-side metric propagation.
  • The previous PR head passed Delta Spark UT. Both this PR and [GLUTEN][VL] Read Delta deletion vectors through Velox #12867 reported the same three now-passing baseline entries, which were removed under the gate's fail-on-fixed policy: one DV test and two unrelated type-widening tests.

Targeted DV reads

A Spark 3.5.4 validation build retained a temporary legacy switch solely to compare both paths from the same build. PR A used executor deferral with native range reading disabled; Legacy used driver loading with native range reading disabled. Native file scan and metadata row index were enabled in both arms. The final PR does not publish the legacy driver-loading switch.

Each arm ran three times in balanced order against the same snapshot and resources.

Query Legacy median PR A median Speedup
Metadata count(*) 8.116 s 7.923 s 1.02x
Physical sum 123.592 s 12.332 s 10.02x
Physical grouped sum 114.912 s 6.753 s 17.02x
Combined physical scans 239.467 s 19.085 s 12.55x
Targeted three-query total 247.583 s 27.008 s 9.17x

The combined physical value is the median of each run's sum + grouped_sum time. SQL-start-to-first-job delay fell from 114.7 s to 0.64 s for sum, and from 111.2 s to 0.38 s for grouped sum.

The snapshot contained 2,461 DV-bearing files and 6,479,887,870 visible rows after applying DV cardinality 720,032,919. Every arm returned identical results.

Full Delta ingestion

A separate balanced three-round test processed all 24 TPC-DS SF2500 tables. Only store_sales carried DVs; native writing, output settings, inputs, and resources were fixed.

Scope Legacy median PR A median Improvement
All 24 tables 820.56 s 693.24 s 15.52% lower
DV-bearing store_sales 372.35 s 254.08 s 31.76% lower
Other 23 tables 446.43 s 440.05 s approximately unchanged

All runs completed 24 of 24 tables with matching schemas, partitioning, Delta metrics, row statistics, and corresponding output row/file counts.

The claims are limited to these Spark 3.5.4 workloads: 12.55x for the two targeted physical DV scans and 15.52% for full ingestion. They do not cover a full query suite, DV creation, native writing, or Spark 4 performance.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: IBM BOB

@github-actions github-actions Bot added CORE works for Gluten Core VELOX DOCS DATA_LAKE labels Aug 20, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

1 similar comment
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi
malinjawi force-pushed the agent/delta-dv-native-range-read branch from bb950e3 to 90aea76 Compare August 23, 2026 08:15
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@malinjawi
malinjawi force-pushed the agent/delta-dv-native-range-read branch from 90aea76 to 62cd99c Compare August 23, 2026 09:55
@malinjawi malinjawi changed the title [GLUTEN][VL] Move Delta deletion vector reads off the driver [GLUTEN][VL] Defer Delta deletion vector reads to executors Aug 23, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@malinjawi
malinjawi force-pushed the agent/delta-dv-native-range-read branch from 62cd99c to 85b52e4 Compare August 23, 2026 10:20
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@malinjawi
malinjawi force-pushed the agent/delta-dv-native-range-read branch from 85b52e4 to 436f32a Compare August 23, 2026 11:12
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

1 similar comment
@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@malinjawi
malinjawi force-pushed the agent/delta-dv-native-range-read branch from 436f32a to 372f498 Compare August 23, 2026 13:01
@github-actions github-actions Bot added the INFRA label Aug 23, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@malinjawi
malinjawi marked this pull request as ready for review August 24, 2026 12:24
@marin-ma

Copy link
Copy Markdown
Contributor

Are there any circumstances that could benefit from driver loading? If not, the legacy implementation should be removed.

@malinjawi

Copy link
Copy Markdown
Contributor Author

@marin-ma I checked the remaining cases and do not see a normal workload that benefits from loading on-disk DVs on the driver. The only theoretical differences are earlier failure for a missing/corrupt sidecar and avoiding a repeated DV request on a retried or speculative task; neither justifies preserving the serial planning path. The standard Delta fallback already reads DVs on executors.

I will remove the rollback config and the legacy on-disk driver branch, keep inline DVs eager because their bytes are already in Delta metadata, and retain spark.gluten.sql.columnar.filescan=false as the broader fallback. Please let me know if you see a compatibility case that requires a different direction.

@github-actions github-actions Bot removed the DOCS label Aug 24, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

1 similar comment
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@marin-ma
marin-ma requested a lite review from Copilot August 26, 2026 09:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Defers Delta on-disk deletion vector (DV) payload reads from driver planning to executor-side split serialization to reduce driver bottlenecks and speed up job start.

Changes:

  • Adds a serializable DV payload abstraction to support deferred executor materialization with per-task memoization.
  • Wires DV read metrics (and descriptor-prep metrics) into native Delta scans and propagates them to executors.
  • Updates/extends Delta DV handoff and deferred-read tests, plus CI known-failure baseline maintenance.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
gluten-substrait/src/main/scala/org/apache/gluten/execution/FileSourceScanExecTransformer.scala Adds hook for format-specific scan metrics to be included in the native scan metrics map
gluten-substrait/src/main/java/org/apache/gluten/substrait/rel/DeltaLocalFilesNode.java Introduces DeletionVectorPayload and updates DeltaFileReadOptions to materialize payload on demand
gluten-delta/src/main/scala/org/apache/gluten/execution/DeltaScanTransformer.scala Registers new DV metrics and passes DV read metrics into DV normalization
gluten-delta/src/main/scala/org/apache/gluten/delta/DeletionVectorReadMetrics.scala Implements deferred task-time accumulator registration for DV payload read metrics
gluten-delta/src/main/java/org/apache/gluten/delta/TaskAccumulatorRegistry.java Adds helper to register deserialized accumulators once TaskContext is available
gluten-delta/src-delta33/main/scala/.../DeltaDeletionVectorScanInfo.scala Implements deferred on-disk DV payload source + memoized executor materialization (Delta 3.3)
gluten-delta/src-delta40/main/scala/.../DeltaDeletionVectorScanInfo.scala Same as above for Delta 4.0
backends-velox/src-delta*/test/... Adds/updates tests validating executor materialization, memoization, and metric propagation
.github/workflows/util/delta-spark-ut/known-failures.txt Removes fixed baseline failures per CI policy

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +122 to +126
// Executor-side metrics only (excludes driverMetricsAlias).
@transient private lazy val executorSideScanMetrics: Map[String, SQLMetric] =
BackendsApiManager.getMetricsApiInstance
.genFileSourceScanTransformerMetrics(sparkContext)
.filter(m => !driverMetricsAlias.contains(m._1))
.filter(m => !driverMetricsAlias.contains(m._1)) ++ additionalScanMetrics

@malinjawi malinjawi Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated. The map is now named nativeScanMetrics, and the comment states that format-specific metrics may be updated on the driver or executors while driver-only aliases are excluded.

private final byte[] payload;

public SerializedDeletionVectorPayload(byte[] payload) {
this.payload = payload == null ? new byte[0] : payload;

@malinjawi malinjawi Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated. SerializedDeletionVectorPayload now clones the constructor input, with a regression test covering mutation of the caller-owned array. The on-disk deferred path is unaffected.

Comment on lines 166 to +168
public byte[] serializedDeletionVector() {
return serializedDeletionVector;
return deletionVectorPayload.materialize();
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated the method documentation to state that on-disk payload materialization may perform blocking filesystem I/O, is intended for executor-side split-to-protobuf conversion, and returns bytes that must not be modified. The existing method name is retained for API compatibility.

Comment on lines +167 to +168
metrics("dvDescriptorCount")
.add(deltaReadOptions.count(_.hasDeletionVector()).toLong)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I checked this path and kept the count where it is. It is a local O(files-per-partition) traversal on the driver; protobuf construction occurs later on the executor. Folding the count into normalization would widen the shared Delta-version API for negligible cost. We can revisit it if profiling shows this traversal is material.

Comment on lines +51 to +54
/** Avoid double registration when Spark deserializes this object after installing TaskContext. */
private def readObject(input: ObjectInputStream): Unit = {
input.defaultReadObject()
registeredInTask = TaskContext.get() != null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I verified the deserialization order and kept the logic unchanged, with a clearer comment. defaultReadObject() deserializes the nested SQLMetrics first, and Spark AccumulatorV2.readObject registers each one when TaskContext exists. The wrapper then records that state to avoid registering them twice. If no context exists, registerForCurrentTask() performs the deferred registration. Resetting the flag to false would append duplicate accumulators to TaskMetrics; the end-to-end tests also assert exactly one reported read attempt.

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@marin-ma marin-ma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some minor comments. Thanks.

deletionVectorPayload: DeletionVectorPayload) {
def serializedDeletionVector: Array[Byte] = deletionVectorPayload.materialize()

def isPayloadMaterialized: Boolean = deletionVectorPayload.isMaterialized()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't see this function being invoked elsewhere. Can you remove it? Ditto for src-delta40

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed isPayloadMaterialized from both the Delta 3.3 and 4.0 implementations. Thanks.

}

/** A payload source for inline DVs whose bytes are already present in Delta metadata. */
public static final class SerializedDeletionVectorPayload implements DeletionVectorPayload {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would it be better to rename to InMemoryDeletionVectorPayload?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Renamed it to InMemoryDeletionVectorPayload and updated all references and tests.

@malinjawi
malinjawi force-pushed the agent/delta-dv-native-range-read branch from c565daa to 6e95beb Compare August 27, 2026 07:14
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi

Copy link
Copy Markdown
Contributor Author

Run Gluten Clickhouse CI

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@marin-ma marin-ma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM. Thanks!

cc: @zhztheplayer Do you have any comments?

@zhztheplayer zhztheplayer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@marin-ma

Copy link
Copy Markdown
Contributor

Some delta UT failed. @malinjawi PTAL.

@malinjawi

Copy link
Copy Markdown
Contributor Author

Some delta UT failed. @malinjawi PTAL.

Yeah, thanks @marin-ma. I checked the failed shards: they report zero new regressions. The failures are caused by 32 stale known-failure entries that now pass after #12821. #12907 removes exactly those entries. Once it merges, I’ll sync main and rerun the Delta CI.

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants