perf(table): pre-size positional delete positions - #1923
Conversation
zeroshade
left a comment
There was a problem hiding this comment.
The unique-position benchmark improves, but sizing the set from raw row count creates severe over-allocation for valid duplicate-heavy delete files.
Blocking — Bound preallocation by expected unique cardinality (table/arrow_scanner.go:466–474)
totalPositions := 0
for _, chunk := range positionalDeletes {
if chunk != nil {
totalPositions += chunk.Len()
}
}
deletes := make(set[int64], totalPositions) // raw rows, not unique positionsPosition deletes are combined across files and may legitimately overlap. With 1,000,000 identical positions across 16 chunks, I measured:
- Previous growth strategy: cardinality 1, 0 B/op, roughly 4–6 ms
- This change: cardinality 1, approximately 37.8 MB/op, 4,098 allocations, roughly 7–20 ms
At larger scales or across concurrent scan tasks, valid overlapping deletes can reserve gigabytes despite producing a tiny set. The current benchmarks use only unique values, so they hide this regression. The capacity allocation also happens before type/null/negative validation.
Please retain cardinality-driven growth or use a benchmark-justified bounded hint such as min(totalPositions, fixedCap). Add duplicate-heavy benchmark coverage alongside the unique cases.
This review was drafted by an AI-assisted tool and confirmed by an Iceberg Go maintainer. After you've addressed the points above and pushed an update, an Iceberg Go maintainer — a real person — will take the next look at the PR. The findings cite the project's review criteria; if you think one of them is mis-applied, please reply on the PR and a maintainer will weigh in.
More on how Iceberg Go handles maintainer review:
CONTRIBUTING.md.
00ec6b4 to
eb2939b
Compare
What changed
Benchmark
Ran on an Apple M1 Pro (
darwin/arm64) with Gogo1.26.3.Median of 5 runs:
Checks
go test ./...go vet ./...go test -race ./table