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

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 2b23a7a15 perf(table): bound scan task channel capacity (#2198)
2b23a7a15 is described below

commit 2b23a7a151b7860329346ae750637f49082af920
Author: Minh Vu <[email protected]>
AuthorDate: Mon Oct 19 18:58:33 2026 +0200

    perf(table): bound scan task channel capacity (#2198)
    
    * perf(table): bound scan task channel to worker count
    
    * test(table): cover bounded scan task dispatch and cancellation
    
    * style(table): gofmt scan task channel test
---
 table/arrow_scanner.go              |  8 +++++++-
 table/arrow_scanner_reorder_test.go | 23 +++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/table/arrow_scanner.go b/table/arrow_scanner.go
index 935a949eb..98556f2f4 100644
--- a/table/arrow_scanner.go
+++ b/table/arrow_scanner.go
@@ -2740,12 +2740,18 @@ func createIteratorWithCleanup(ctx context.Context, 
numWorkers uint, records <-c
        }
 }
 
+// newScanTaskChannel buffers enough work to keep scan workers busy without
+// copying the entire task list into the channel for large scans.
+func newScanTaskChannel(taskCount, numWorkers int) chan 
tblutils.Enumerated[FileScanTask] {
+       return make(chan tblutils.Enumerated[FileScanTask], min(taskCount, 
2*numWorkers))
+}
+
 func (as *arrowScan) recordBatchesFromTasksAndDeletes(ctx context.Context, 
tasks []FileScanTask, positionDeleteLoader *lazyPositionDeleteLoader, dvLoader 
*lazyDeletionVectorLoader, equalityDeleteLoader *lazyEqualityDeleteLoader, 
invariants *arrowScanInvariants) iter.Seq2[arrow.RecordBatch, error] {
        return func(yield func(arrow.RecordBatch, error) bool) {
                extSet := substrait.NewExtensionSet()
                scanCtx, cancel := 
context.WithCancelCause(exprs.WithExtensionIDSet(ctx, extSet))
                numWorkers := min(as.concurrency, len(tasks))
-               taskChan := make(chan tblutils.Enumerated[FileScanTask], 
len(tasks))
+               taskChan := newScanTaskChannel(len(tasks), numWorkers)
                records := make(chan enumeratedRecord, numWorkers)
 
                var wg sync.WaitGroup
diff --git a/table/arrow_scanner_reorder_test.go 
b/table/arrow_scanner_reorder_test.go
index a754c759c..1cd5c90b9 100644
--- a/table/arrow_scanner_reorder_test.go
+++ b/table/arrow_scanner_reorder_test.go
@@ -218,6 +218,26 @@ func writeReorderDataFile(tb testing.TB, arrowSchema 
*arrow.Schema, path string,
        return bldr.Build()
 }
 
+func TestScanTaskChannelCapacity(t *testing.T) {
+       for _, tc := range []struct {
+               name         string
+               taskCount    int
+               numWorkers   int
+               wantCapacity int
+       }{
+               {name: "empty", taskCount: 0, numWorkers: 0, wantCapacity: 0},
+               {name: "single task", taskCount: 1, numWorkers: 1, 
wantCapacity: 1},
+               {name: "fewer tasks than capacity", taskCount: 3, numWorkers: 
3, wantCapacity: 3},
+               {name: "many tasks", taskCount: 100_000, numWorkers: 4, 
wantCapacity: 8},
+               {name: "single worker", taskCount: 100_000, numWorkers: 1, 
wantCapacity: 2},
+       } {
+               t.Run(tc.name, func(t *testing.T) {
+                       queue := newScanTaskChannel(tc.taskCount, tc.numWorkers)
+                       require.Equal(t, tc.wantCapacity, cap(queue))
+               })
+       }
+}
+
 func TestArrowScanReorderHeapBoundedWhileHeadTaskLags(t *testing.T) {
        const (
                files       = 32
@@ -280,6 +300,9 @@ func 
TestArrowScanReorderCancelWhileWorkersWaitForTaskCredits(t *testing.T) {
        )
 
        synctest.Test(t, func(t *testing.T) {
+               // With the first task gated, these tasks also fill and block 
the producer.
+               require.Greater(t, files, 
numWorkers+cap(newScanTaskChannel(files, numWorkers)))
+
                dir := filepath.ToSlash(t.TempDir())
                gateIO := &reorderGateIO{}
                tbl, tasks := newReorderScanFixture(t, dir, files, rowsPerFile, 
gateIO)

Reply via email to