Skip to content

Spark 4.1: Add per-task scanDuration metric - #17562

Open
venkata91 wants to merge 1 commit into
apache:mainfrom
venkata91:spark-task-scan-duration-metric
Open

Spark 4.1: Add per-task scanDuration metric#17562
venkata91 wants to merge 1 commit into
apache:mainfrom
venkata91:spark-task-scan-duration-metric

Conversation

@venkata91

@venkata91 venkata91 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #17563.

Iceberg reports scan bytes and file/manifest counts per task, but the only timer is totalPlanningDuration, which covers driver-side planning. There is no metric for how long a task spent reading, so scan throughput cannot be derived from Iceberg metrics alone.

Changes

Add scanDuration: wall time a task spends in BaseReader.next(), covering split open and row/batch iteration.

  • Timed per next() call, not per row. Spark makes the same tradeoff for scanTime in DataSourceScanExec.
  • Accumulated in a finally, so a task that throws mid-scan still reports what it read.
  • TaskScanDuration from BatchDataReader and RowDataReader, aggregated by ScanDuration, mirroring the TotalPlanningDuration pair.

Nanoseconds, not the milliseconds used by totalPlanningDuration: a split can be read in well under a millisecond, so ms would round most per-task reads to zero. The aggregate is formatted ns/us/ms/s for the UI.

Testing done

TestSparkReadMetrics asserts scanDuration > 0 for V1, V2 and V3 tables. 3 tests, 0 failures. spotlessCheck and checkstyleMain pass.

Open questions

  • Scoped to spark/v4.1. Happy to backport to 4.0 and 3.5 here or in a follow-up.
  • Timer wraps next() to cover both readers. If reviewers prefer it around open() only, excluding iteration, that is a small change.

@github-actions github-actions Bot added the spark label Aug 9, 2026
@venkata91
venkata91 force-pushed the spark-task-scan-duration-metric branch from 02e75bf to b88f53d Compare August 9, 2026 02:29
Iceberg reports scan bytes and file/manifest counts per task, but the only
timer in the metrics system is totalPlanningDuration, which measures
driver-side planning. There is no metric for how long a task spent actually
reading data, so a scan's throughput cannot be derived from Iceberg metrics
alone.

Add scanDuration: wall time a task spends in BaseReader.next(), accumulated
per call rather than per row so the timer costs nothing measurable relative
to the read. Emitted as TaskScanDuration from BatchDataReader and
RowDataReader, aggregated by ScanDuration, mirroring the existing
TotalPlanningDuration pair.

Values are nanoseconds: a single split can be read in well under a
millisecond, so a millisecond timer would round most per-task reads to zero.
ScanDuration formats the aggregate as ns/us/ms/s for the UI.

Generated-by: Claude Opus 5

@anoopj anoopj 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.

The code change looks good to me. We might be missing code coverage for the non-vectorized path (RowDataReader) because the Spark read follows the vectorized path?

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.

Spark: No metric for time spent reading data in a scan task

2 participants