perf: Write compressed directly to buffer - #10833
Conversation
|
run benchmarks arrow_ipc |
|
🤖 Arrow criterion benchmark running (GKE) | trigger CPU Details (lscpu)Comparing compress_directly (32bfb62) to 7d9bdfd (merge-base) diff Run configurationrun benchmark arrow_ipcBENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench arrow_ipc File an issue against this benchmark runner |
|
Benchmark for this request failed before finishing (Kubernetes reason: Benchmarks requested: Kubernetes messageFile an issue against this benchmark runner |
|
run benchmarks ipc_writer |
|
🤖 Arrow criterion benchmark running (GKE) | trigger CPU Details (lscpu)Comparing compress_directly (32bfb62) to 7d9bdfd (merge-base) diff Run configurationrun benchmark ipc_writerBENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench ipc_writer File an issue against this benchmark runner |
alamb
left a comment
There was a problem hiding this comment.
Makes sense to me -- thank you @EmilyMatt and @Rich-T-kid
Even if the benchmarks don't show a measurable win as long as they don't slow down I think this PR is a win
| let result = context.zstd_compressor(level).compress(input)?; | ||
| output.extend_from_slice(&result); | ||
| let start = output.len(); | ||
| output.reserve(zstd::zstd_safe::compress_bound(input.len())); |
There was a problem hiding this comment.
Internally compress() also calls compress_bound for the allocation size
https://docs.rs/zstd/0.13.3/src/zstd/bulk/compressor.rs.html#132
So I think this is no worse (and better as it avoids a copy)
There was a problem hiding this comment.
Yeah I just took it from the function itself as it seems to do all those steps except into a new Vec
|
🤖 Arrow criterion benchmark completed (GKE) | trigger Instance: Comparing compress_directly (32bfb62) to 7d9bdfd (merge-base) diff Run configurationrun benchmark ipc_writerCPU Details (lscpu)Details
Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
are the dictionary benchmarks noisy or is this causing a real regression in the dictionary case 🤔 |
|
run benchmarks ipc_writer |
1 similar comment
|
run benchmarks ipc_writer |
|
🤖 Arrow criterion benchmark running (GKE) | trigger CPU Details (lscpu)Comparing compress_directly (f90306f) to 2a82e59 (merge-base) diff Run configurationrun benchmark ipc_writerBENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench ipc_writer File an issue against this benchmark runner |
|
🤖 Arrow criterion benchmark running (GKE) | trigger CPU Details (lscpu)Comparing compress_directly (f90306f) to 2a82e59 (merge-base) diff Run configurationrun benchmark ipc_writerBENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench ipc_writer File an issue against this benchmark runner |
|
🤖 Arrow criterion benchmark completed (GKE) | trigger Instance: Comparing compress_directly (f90306f) to 2a82e59 (merge-base) diff Run configurationrun benchmark ipc_writerCPU Details (lscpu)Details
Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
🤖 Arrow criterion benchmark completed (GKE) | trigger Instance: Comparing compress_directly (f90306f) to 2a82e59 (merge-base) diff Run configurationrun benchmark ipc_writerCPU Details (lscpu)Details
Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
the benchmark its self looks fine so i dont think this is noise - arrow-rs/arrow-ipc/benches/ipc_writer.rs Line 119 in 2a82e59 |
I can't seem to reproduce anything conclusive locally StreamWriter/write_10/zstd
StreamEncoder/encode_10/zstd
(I thought maybe the issue is that the benchmark oes a single encode which would be better with reserve_exact as that might save a reallocation in some specific cases, but even if that proves better for those cases, it's irrelevant for real life use, since after the encode() call there will be others, meaning the vec would be reallocated anyway after the reserve_exact, making it worse, rather than better) |
Yeah I agree this benchmark seems to be overly sensitve to allocation patterns. Let's just merge this on its merits |
|
Thank you @Rich-T-kid and @EmilyMatt |
Currently we have to allocate twice when compressing using zstd - once to a temporary vec, which is the output from the compress(input) call, and then extend our output buffer with extend_from_slice which causes another realloc(especially if writing a large buffer)
instead we can use the zstd compress_to_buffer function directly, which is what the compress() call does anyway.