Conversation
…1148) `DeltaBitPackEncoder::new` preallocated a 1MiB bit writer buffer. Byte array columns eagerly construct their fallback encoder, and `DELTA_BYTE_ARRAY` holds two of these, so every column paid 2MiB of heap up front even if the fallback was never used. Start with an empty buffer instead; it grows on demand and retains its capacity across pages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ReVtW5wMiSAmHnPrnDxhCk
|
run benchmark arrow_writer |
|
run benchmark writer_overhead |
|
🤖 Arrow criterion benchmark running (GKE) | trigger CPU Details (lscpu)Comparing fix-delta-bitpack-prealloc (29b3b6e) to af18bac (merge-base) diff Run configurationrun benchmark arrow_writer
env:
BENCH_FILTER: "parquet_2|delta_byte_array"BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench arrow_writer File an issue against this benchmark runner |
|
🤖 Arrow criterion benchmark running (GKE) | trigger CPU Details (lscpu)Comparing fix-delta-bitpack-prealloc (29b3b6e) to af18bac (merge-base) diff Run configurationrun benchmark writer_overheadBENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench writer_overhead File an issue against this benchmark runner |
|
🤖 Arrow criterion benchmark completed (GKE) | trigger Instance: Comparing fix-delta-bitpack-prealloc (29b3b6e) to af18bac (merge-base) diff Run configurationrun benchmark writer_overheadCPU Details (lscpu)Details
Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
🤖 Arrow criterion benchmark completed (GKE) | trigger Instance: Comparing fix-delta-bitpack-prealloc (29b3b6e) to af18bac (merge-base) diff Run configurationrun benchmark arrow_writer
env:
BENCH_FILTER: "parquet_2|delta_byte_array"CPU Details (lscpu)Details
Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
Which issue does this PR close?
Rationale for this change
DeltaBitPackEncoder::newpreallocates a 1MiB buffer for its bit writer. Byte array columns eagerly construct their fallback encoder, and theDELTA_BYTE_ARRAYfallback (the default forPARQUET_2_0) holds twoDeltaBitPackEncoders, so every byte array column pays 2MiB of heap up front, even when it dictionary encodes and the fallback is never used. With 100 columns that is ~200MiB.The preallocation only ever helped the first page: the buffer is a
Vecthat retains its capacity acrossclear().What changes are included in this PR?
DeltaBitPackEncoderstarts with an empty bit writer buffer that grows on demand (removesDEFAULT_BIT_WRITER_SIZE). This also benefitsDELTA_BINARY_PACKEDandDELTA_LENGTH_BYTE_ARRAY.unused_delta_fallback_does_not_preallocateinparquet/tests/arrow_writer, using the existing peak heap tracking allocator. It fails onmain(peak ≈ 210MB) and passes with this change.Are these changes tested?
Yes, with the new regression test above. The existing lib and
arrow_writertests pass.Benchmarks (criterion,
--save-baselineonmainvs this branch):arrow_writerdelta byte array:writer_overhead:The other
parquet_2/zstd_parquet_2writer benchmarks are within noise after re-running. The one exception isint32_ree_95pct_null/parquet_2, which measured +2.6% to +5.1% across runs. However,mainmeasured against its own baseline drifted +0.9% to +2.7% on this benchmark, and it does not exercise the delta encoder, so the difference looks like noise.Are there any user-facing changes?
No API changes. Lower peak memory when writing many byte array columns with
PARQUET_2_0/ delta encodings.🤖 Generated with Claude Code