Skip to content

feat(ipc): Avoid zero-filling IPC reads with typed buffer handling#9971

Open
pchintar wants to merge 1 commit into
apache:mainfrom
pchintar:ipc-typed-buffer-reads
Open

feat(ipc): Avoid zero-filling IPC reads with typed buffer handling#9971
pchintar wants to merge 1 commit into
apache:mainfrom
pchintar:ipc-typed-buffer-reads

Conversation

@pchintar
Copy link
Copy Markdown
Contributor

@pchintar pchintar commented May 14, 2026

Which issue does this PR close?

Rationale for this change

This PR is a follow-up to the alignment concerns raised in #9778 when using Vec<u8> for IPC body reads to replace the current MutableBuffer::from_len_zeroed in IPC Reader.

My earlier approach showed that reading directly into Vec<u8> could substantially reduce redundant zero-filling in IPC reader paths, but some decode paths still relied on fixed-width typed buffers that could require additional alignment handling cost later during array construction.

This PR keeps the Vec<u8>-based read path for IPC message and block bodies, while adding typed IPC buffer handling for fixed-width physical buffers before array construction.

This preserves the existing alignment behavior for those fixed-width decode paths while avoiding the additional alignment handling/copying costs that could otherwise occur later during array construction.

The typed-buffer handling now covers:

  • primitive and primitive-like arrays
  • binary/string offset buffers
  • list and list-view offsets/sizes
  • dictionary index buffers
  • view buffers

These paths now read their physical buffers through next_typed_buffer::<T>() so the expected physical buffer lengths are derived from the native value type before array construction.

Exception Case: UnionArray requires ScalarBuffer inputs directly, and external IPC producers may provide unaligned union type id or offset buffers. The updated Union handling therefore preserves the aligned fast path while falling back to aligned ScalarBuffer construction only for unaligned external union buffers.

Container types such as Struct, FixedSizeList, RunEndEncoded, and similar nested/container arrays were intentionally left on their existing decode paths because they do not directly own fixed-width value buffers at that level. Their child arrays continue to decode recursively through the updated typed-buffer paths where applicable.

Are these changes tested?

Yes.

The existing IPC reader test suite was run with:

cargo test -p arrow-ipc --lib

IPC reader benchmark was also run with:

cargo bench -p arrow-ipc --bench ipc_reader --features zstd

The non-compressed, non-mmap IPC reader paths showed consistent improvements locally. Compressed and mmap-heavy paths were mostly neutral, as expected.

Are there any user-facing changes?

No.

@github-actions github-actions Bot added the arrow Changes to the arrow crate label May 14, 2026
@pchintar pchintar force-pushed the ipc-typed-buffer-reads branch from b59bbe2 to e8845d0 Compare May 14, 2026 02:28
@pchintar pchintar changed the title Avoid zero-filling IPC reads with typed buffer handling feat(ipc): Avoid zero-filling IPC reads with typed buffer handling May 14, 2026
@pchintar pchintar force-pushed the ipc-typed-buffer-reads branch 3 times, most recently from 292cb21 to cabe3f2 Compare May 14, 2026 05:56
@pchintar
Copy link
Copy Markdown
Contributor Author

@alamb and @adriangb could you pls run benchmark ipc_reader

@Dandandan
Copy link
Copy Markdown
Contributor

run benchmark ipc_reader

@adriangbot
Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4448280608-73-znvcv 6.12.68+ #1 SMP Wed Apr 1 02:23:28 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing ipc-typed-buffer-reads (cabe3f2) to 1ffd202 (merge-base) diff
BENCH_NAME=ipc_reader
BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench ipc_reader
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot
Copy link
Copy Markdown

🤖 Arrow criterion benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                                       ipc-typed-buffer-reads                 main
-----                                                       ----------------------                 ----
arrow_ipc_reader/FileReader/no_validation/read_10           1.00     86.8±0.47µs        ? ?/sec    1.43    124.4±5.17µs        ? ?/sec
arrow_ipc_reader/FileReader/no_validation/read_10/mmap      1.02     57.9±0.39µs        ? ?/sec    1.00     56.6±0.37µs        ? ?/sec
arrow_ipc_reader/FileReader/read_10                         1.00   377.9±43.54µs        ? ?/sec    1.08   407.7±52.57µs        ? ?/sec
arrow_ipc_reader/FileReader/read_10/mmap                    1.00   462.4±54.58µs        ? ?/sec    1.01   467.7±53.99µs        ? ?/sec
arrow_ipc_reader/StreamReader/no_validation/read_10         1.00     87.3±0.83µs        ? ?/sec    1.41    123.0±1.75µs        ? ?/sec
arrow_ipc_reader/StreamReader/no_validation/read_10/zstd    1.00      2.4±0.02ms        ? ?/sec    1.00      2.4±0.02ms        ? ?/sec
arrow_ipc_reader/StreamReader/read_10                       1.00   355.4±54.52µs        ? ?/sec    1.14   406.6±55.70µs        ? ?/sec
arrow_ipc_reader/StreamReader/read_10/zstd                  1.00      2.7±0.03ms        ? ?/sec    1.00      2.7±0.07ms        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 85.0s
Peak memory 2.7 GiB
Avg memory 2.6 GiB
CPU user 71.7s
CPU sys 10.3s
Peak spill 0 B

branch

Metric Value
Wall time 90.0s
Peak memory 2.7 GiB
Avg memory 2.6 GiB
CPU user 76.2s
CPU sys 9.7s
Peak spill 0 B

File an issue against this benchmark runner

Copy link
Copy Markdown
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @pchintar -- this is getting closer but I think this still may cause issues.

I think any time we allocate (or reallcoate) a Vec<u8> we lose the alignment guarantee's. There are still several places in this PR that do Vec::new(...)

Poking around I found a way to to get an aligned vector that maybe we can try here

https://stackoverflow.com/questions/60180121/how-do-i-allocate-a-vecu8-that-is-aligned-to-the-size-of-the-cache-line

So instead of this code

    let mut buf = MutableBuffer::from_len_zeroed(total_len);
    reader.read_exact(&mut buf)?;
    Ok(buf.into())

We could do something like

    let mut buf = aligned_vec(total_len);
    reader.read_exact(&mut buf)?;
    Ok(buf.into())

And as long as aligned_vec was aligned to (1<<6) (64) I think it would be equivalent to the current mutable buffer. Maybe we should align to 128 to guarantee views work 🤔

Comment thread arrow-ipc/src/reader.rs Outdated
/// reads.
enum IpcBufferSource<'a> {
Buffer(&'a Buffer),
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stylistically if you want to make a wrapper type I think a more common pattern is a an "new type" struct -- something like

struct IpcBufferSource<'a>(&'a Buffer)

That way you can still define methods on it, but you don't have to use match all over the place - you can just refer to the inner field as .0

Copy link
Copy Markdown
Contributor Author

@pchintar pchintar May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fixed now, thnx

Comment thread arrow-ipc/src/reader.rs
compression: Option<CompressionCodec>,
decompression_context: &mut DecompressionContext,
) -> Result<Buffer, ArrowError> {
let byte_len = len
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the naming a little confusing here as there are three buffers

I found this a little confusing as there three buffers -- self::Buffer, buf (the input buffer) and the output buffer

Can we maybe name them something more specific to distinguish them? I am in particular confused about the buffer in self and the one passed in via the argument

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have replaced with more exact variable names & also added more documentation here

Comment thread arrow-ipc/src/reader.rs
ArrowError::IpcError("Buffer count mismatched with metadata".to_string())
})?;

self.data.read_typed_buffer::<T>(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part looks good, so far

Comment thread arrow-ipc/src/reader.rs Outdated
// Some invalid or legacy IPC inputs may contain shorter buffers than
// implied by the schema. Preserve the existing behavior and let array
// construction/validation report the error.
if buffer.len() <= byte_len || buffer.as_ptr().align_offset(std::mem::align_of::<T>()) != 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doens't seem right -- our change should ensure that the buffer is always aligned correctly to the otutput requirements. The fact you have to check afterwards suggests this is not the case

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the "buffer.as_ptr().align_offset(std::mem::align_of::()) != 0" part as it was redundant

Comment thread arrow-ipc/src/reader.rs
buf.len()
)));
}
Ok(Buffer::from_vec(buf))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this Vec and the one below (still) has no guaranteed alignment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this is always safe though & there's a net gain in speed nonetheless, so for
aligned case:
old/current path: zero-fill + read
new path: read only
=> faster

unaligned case:
old/current path: zero-fill + read
new path: read + alignment copy
=> ~same almost

@pchintar pchintar force-pushed the ipc-typed-buffer-reads branch 2 times, most recently from 51fd033 to f1d1c3a Compare May 15, 2026 04:48
@pchintar
Copy link
Copy Markdown
Contributor Author

pchintar commented May 15, 2026

@adriangbot and @Dandandan could you pls run benchmark ipc_reader

@adriangb
Copy link
Copy Markdown
Contributor

run benchmark ipc_reader

@adriangbot
Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4457171942-121-7hf6g 6.12.68+ #1 SMP Wed Apr 1 02:23:28 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing ipc-typed-buffer-reads (f1d1c3a) to 1ffd202 (merge-base) diff
BENCH_NAME=ipc_reader
BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench ipc_reader
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot
Copy link
Copy Markdown

🤖 Arrow criterion benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                                       ipc-typed-buffer-reads                 main
-----                                                       ----------------------                 ----
arrow_ipc_reader/FileReader/no_validation/read_10           1.00     87.5±0.70µs        ? ?/sec    1.42    124.5±2.24µs        ? ?/sec
arrow_ipc_reader/FileReader/no_validation/read_10/mmap      1.02     57.3±0.40µs        ? ?/sec    1.00     56.2±0.27µs        ? ?/sec
arrow_ipc_reader/FileReader/read_10                         1.00   356.5±54.96µs        ? ?/sec    1.15   408.3±48.43µs        ? ?/sec
arrow_ipc_reader/FileReader/read_10/mmap                    1.00   462.3±54.18µs        ? ?/sec    1.00   464.0±52.08µs        ? ?/sec
arrow_ipc_reader/StreamReader/no_validation/read_10         1.00     92.3±0.97µs        ? ?/sec    1.32    122.0±2.02µs        ? ?/sec
arrow_ipc_reader/StreamReader/no_validation/read_10/zstd    1.00      2.4±0.02ms        ? ?/sec    1.00      2.5±0.03ms        ? ?/sec
arrow_ipc_reader/StreamReader/read_10                       1.00   383.1±42.10µs        ? ?/sec    1.05   403.3±53.62µs        ? ?/sec
arrow_ipc_reader/StreamReader/read_10/zstd                  1.00      2.7±0.03ms        ? ?/sec    1.00      2.7±0.07ms        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 85.0s
Peak memory 2.7 GiB
Avg memory 2.7 GiB
CPU user 74.5s
CPU sys 10.1s
Peak spill 0 B

branch

Metric Value
Wall time 85.0s
Peak memory 2.7 GiB
Avg memory 2.6 GiB
CPU user 74.0s
CPU sys 10.6s
Peak spill 0 B

File an issue against this benchmark runner

Comment thread arrow-buffer/src/buffer/immutable.rs Outdated

fn deref(&self) -> &[u8] {
// Safety: `ptr` points to `len` bytes owned by this AlignedVec.
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it could expose uninitialized data from safe code. I think this implementation has the same soundness issue as the one using Vec::with_capactiy and Vec::set_len.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this still exposes the allocation as initialized [u8] through Deref/DerefMut before the reader has actually filled it, so it has the same issue as the earlier Vec::with_capacity + set_len approach.

I also explored the aligned-allocation direction separately by allocating through an aligned backing type and then converting back to Vec<u8>, but that ran into layout/deallocation issues under Miri because the allocation alignment was no longer preserved through the Vec<u8> ownership path.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

Taking a step back I think what we would have to do is to change the structure of the reader from "read a Page and then convert it to the right kind of buffer" so that any time the code needs to read a page we pass in the resulting type.

I think you partly did this in this PR, but for some reasons I don't fully understand the read_page is still in terms of Vec rather than Vec<T>

One thing I did notice was that when the pages are compressed, they need to be read as Vec (or at least the alignment isn't critiical as they get decompressed again immediately)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I see the remaining gap now: next_typed_buffer<T>() centralizes the typed length handling, but it still receives data from the existing byte-oriented body buffer path.

I’ll rework this revision to remove the unsound aligned allocation experiment and keep the typed-buffer handling focused on the fixed-width decode paths. For compressed buffers I’ll leave the existing byte-oriented path unchanged, since decompression already materializes a new buffer anyway.

Copy link
Copy Markdown
Contributor Author

@pchintar pchintar May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make the deeper Vec<T> version fully safe, the implementation would have to be something like:

uncompressed fixed-width buffer
  -> read/slice bytes
  -> copy/convert into Vec<T>
  -> Buffer::from_vec(Vec<T>)

That would produce a properly typed/aligned final buffer, but it would also add a byte->typed copy for every uncompressed fixed-width buffer and that could diminish the speed gains imo.

The version I don’t think is safe is:

Vec<T>::with_capacity(len)
  -> expose spare capacity as bytes
  -> Read::read_exact(...)
  -> Buffer::from_vec(Vec<T>)

because that still needs an uninitialized read path on stable Rust.

So the alignment tradeoff is this: a fully typed/aligned read path for uncompressed fixed-width buffers would need either an uninitialized read path into Vec<T>/typed storage, or a safe but extra byte->typed copy before Buffer::from_vec(Vec<T>).

So for this revision I’m using neither of both by trying to avoid adding a new copy to the uncompressed hot path, and keep the change focused on next_typed_buffer<T>() doing the typed physical length handling before array construction.

@pchintar pchintar force-pushed the ipc-typed-buffer-reads branch from f1d1c3a to 6c63301 Compare May 15, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arrow Changes to the arrow crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove redundant zero-initialization in Arrow IPC reader hot paths

6 participants