Skip to content

feat(arrow-ipc): add sans-IO stream encoder#10277

Open
Phoenix500526 wants to merge 4 commits into
apache:mainfrom
Phoenix500526:issue/7812
Open

feat(arrow-ipc): add sans-IO stream encoder#10277
Phoenix500526 wants to merge 4 commits into
apache:mainfrom
Phoenix500526:issue/7812

Conversation

@Phoenix500526

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

StreamWriter currently requires a std::io::Write sink, which is awkward for async or chunk-oriented destinations such as object stores. This PR adds a sans-IO IPC stream encoder so callers can encode Arrow IPC stream data into ordered Buffer chunks and send those chunks through their own IO layer.

What changes are included in this PR?

This PR adds StreamEncoder, a stateful IPC stream encoder that:

  • emits ordered arrow_buffer::Buffer chunks
  • hides stream lifecycle details such as schema emission and EOS markers
  • owns stream state such as dictionary tracking and IPC write context
  • preserves the low-copy path for uncompressed record batch body buffers
  • supports try_new, try_new_with_options, encode, and finish

Are these changes tested?

Yes.
Added tests compare StreamEncoder output byte-for-byte with StreamWriter output for:
a normal record batch stream
an empty stream
a stream containing dictionary batches

Are there any user-facing changes?

Yes. This adds a new public arrow_ipc::writer::StreamEncoder API.
There are no breaking changes. Existing StreamWriter behavior is unchanged.

@github-actions github-actions Bot added the arrow Changes to the arrow crate label Jul 3, 2026
@Rich-T-kid

Copy link
Copy Markdown
Contributor

I'll try and give this a review within a few days

@Rich-T-kid Rich-T-kid left a comment

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 took a brief glance, looks pretty good to me so far. I can take a more in depth look tomorrow. I left a suggestion 🚀

Comment thread arrow-ipc/src/writer.rs Outdated
/// # }
/// ```
///
/// [IPC Streaming Format]: https://arrow.apache.org/docs/format/Columnar.html#ipc-streaming-format

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.

we can remove the comment/link to the IPC format

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.

Thanks for the review. The comment is removed in commit 6bea182

Comment thread arrow-ipc/src/writer.rs Outdated

// StreamEncoder and StreamWriter currently use separate encoding paths, so these tests
// verify the new sans-IO API preserves the existing IPC stream byte layout.
#[test]

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.

Not strictly necessary, but since the originating issue for this PR wanted to use StreamWriter in an async context, could you add a test that mirrors the flow of an async writer (tokio is already a dev-dependency here) and then assert the final bytes against a sync StreamWriter?

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.

Done

@Phoenix500526
Phoenix500526 force-pushed the issue/7812 branch 2 times, most recently from 234c1f6 to 94eaf13 Compare July 16, 2026 01:16

@Rich-T-kid Rich-T-kid left a comment

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.

thank you @Phoenix500526, I think there's value in having a sans-I/O stream encoder, but we need to be careful about the duplication we're adding to arrow-ipc. The file is already hard to understand without much context, and adding duplicate logic in two places makes it hard to maintain.
The tests showcase a good way this can be used, but I'd like the implementation to be leaner. I left a few suggestion let me know what you think

Comment thread arrow-ipc/src/writer.rs
Comment on lines +2836 to +2837
assert_eq!(reader.next().unwrap().unwrap(), batch);
assert!(reader.next().is_none());

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.

nice

Comment thread arrow-ipc/src/writer.rs Outdated
Comment on lines +745 to +778
let capacity = batch
.columns()
.iter()
.map(|a| estimate_encoded_buffer_count(a.data_type()))
.sum();
let mut encoded_buffers: Vec<EncodedBuffer> = Vec::with_capacity(capacity);
let (ipc_message, body_len, tail_pad) = self.record_batch_to_bytes(
batch,
write_options,
ipc_write_context,
&mut IpcBodySink::Collect(&mut encoded_buffers),
)?;

let alignment = write_options.alignment;
let alignment_mask = usize::from(alignment - 1);
let prefix_size = if write_options.write_legacy_ipc_format {
4
} else {
8
};
let ipc_message_len = ipc_message.len();
let aligned_size = (ipc_message_len + prefix_size + alignment_mask) & !alignment_mask;
push_continuation_buffer(out, write_options, (aligned_size - prefix_size) as i32)?;
out.push(Buffer::from(ipc_message));
push_padding_buffer(out, aligned_size - ipc_message_len - prefix_size);
for enc in encoded_buffers {
let len = enc.len();
let buffer = match enc {
EncodedBuffer::Raw(buffer) => buffer,
EncodedBuffer::Compressed(bytes) => Buffer::from(bytes),
};
out.push(buffer);
push_padding_buffer(out, pad_to_alignment(alignment, 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 think the biggest issue I see with this PR is logic duplication. This is very similar to the existing approach.
With the IpcBodySink enum I think we can have a strong shared interface than this.

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.

Good catch. I refactored this to use a shared internal IpcMessageSink for the final framed IPC message emission. I kep IpcBodySink focused on materializing the record batch body buffers, and added IpcMessageSink one layer above it to handle where the complete framed IPC message goes: either a Write sink or ordered Buffers.

With that, IpcDataGenerator::write and encode_to_buffers now share the same write_to_sink path instead of duplicating dictionary/message framing logic.

Comment thread arrow-ipc/src/writer.rs
Comment on lines +1712 to +1719
self.data_gen.encode_to_buffers(
batch,
&mut self.dictionary_tracker,
&self.write_options,
&mut self.ipc_write_context,
&mut out,
)?;
Ok(out)

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.

Maybe instead of a new encode_to_buffers method we could reuse IpcDataGenerator::write? It already uses the IpcBodySink::collect() variant. it does mostly the same thing.

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.

Good point. I agree the two paths should share more of the implementation.

I looked at reusing IpcDataGenerator::write directly, but I don’t think that is quite the right boundary. write commits the output to a Write sink, while StreamEncoder needs to return ordered Buffers. Adapting the buffer path through Write would flatten the output and lose the buffer-preserving behavior this API is trying to expose.

I refactored this by adding an internal IpcMessageSink for the final framed-message emission. IpcBodySink still handles record-batch body materialization, and IpcMessageSink handles emitting the complete framed IPC message to either Write or Vec<Buffer>. This lets write and encode_to_buffers share the same pipeline without forcing the buffer API through Write.

Comment thread arrow-ipc/src/writer.rs Outdated
pub arrow_data: Vec<u8>,
}

fn encoded_data_to_buffers(

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.

can you add a doc comment to these functions

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.

Added in ef60c48

Comment thread arrow-ipc/src/writer.rs
stream_reader.next().unwrap().unwrap()
}

fn encode_stream(

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.

can you add a doc comment. maybe provide a small example of when to use this?

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.

Added in ef60c48

Comment thread arrow-ipc/src/writer.rs
assert_eq!(reader.next().unwrap().unwrap(), batch);
assert!(reader.next().is_none());
}

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 the test here look fine

@Phoenix500526
Phoenix500526 force-pushed the issue/7812 branch 2 times, most recently from 09d05ce to 42a7696 Compare July 17, 2026 05:54
Introduce StreamEncoder for IPC streaming without requiring a
std::io::Write sink. The encoder owns stream state, emits ordered Buffer
chunks, and preserves the low-copy path for uncompressed record batch
body buffers.

Add byte-for-byte compatibility tests against StreamWriter for normal
batches, empty streams, and dictionary batches.

Closes apache#7812
Signed-off-by: Jiawei Zhao <Phoenix500526@163.com>
Exercise StreamEncoder with a Tokio AsyncWrite flow and compare the
bytes with StreamWriter. This keeps the PR tied to the async writer
use case from the original issue.

Refs apache#7812

Signed-off-by: Jiawei Zhao <Phoenix500526@163.com>
Route writer and buffer output through a shared internal sink.
This avoids duplicated IPC framing while preserving Buffer output.

Signed-off-by: Jiawei Zhao <Phoenix500526@163.com>
@Rich-T-kid

Copy link
Copy Markdown
Contributor

@Phoenix500526 is this good for review?

@Phoenix500526

Phoenix500526 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

@Phoenix500526 is this good for review?

@Rich-T-kid Yes, this is ready for review. Thanks for checking.

@Rich-T-kid Rich-T-kid left a comment

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 looks pretty good. I left a couple of suggestions. Thank you for splitting up the commits into separate independent chunks!

Would be nice to validate that this PR didn't accidentally slow down the Stream writer somehow.

Comment thread arrow-ipc/src/writer.rs
Comment on lines +518 to +523
let root = message.finish();
fbb.finish(root, None);

let data = fbb.finished_data();
let metadata = fbb.finished_data();
EncodedData {
ipc_message: data.to_vec(),
ipc_message: metadata.to_vec(),

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.

nice, renamng data to metadata is a nice change

Comment thread arrow-ipc/src/writer.rs
Comment on lines +857 to +866
) -> Result<IpcWriteMetadata, ArrowError> {
let mut sink = IpcMessageSink::Buffers(out);
self.write_to_sink(
batch,
dictionary_tracker,
write_options,
ipc_write_context,
&mut sink,
)
}

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.

nice, this is a lot cleaner, and removes duplication

Comment thread arrow-ipc/src/writer.rs Outdated
Comment on lines -2019 to -2074
fn encoded_data_to_buffers(
out: &mut Vec<Buffer>,
encoded: EncodedData,
write_options: &IpcWriteOptions,
) -> Result<(usize, usize), ArrowError> {
let arrow_data_len = encoded.arrow_data.len();
if arrow_data_len % usize::from(write_options.alignment) != 0 {
return Err(ArrowError::MemoryError(
"Arrow data not aligned".to_string(),
));
}

let alignment_mask = usize::from(write_options.alignment - 1);
let flatbuf_size = encoded.ipc_message.len();
let prefix_size = if write_options.write_legacy_ipc_format {
4
} else {
8
};
let aligned_size = (flatbuf_size + prefix_size + alignment_mask) & !alignment_mask;
let padding_bytes = aligned_size - flatbuf_size - prefix_size;

push_continuation_buffer(out, write_options, (aligned_size - prefix_size) as i32)?;
if flatbuf_size > 0 {
out.push(Buffer::from(encoded.ipc_message));
}
push_padding_buffer(out, padding_bytes);

let body_len = if arrow_data_len > 0 {
out.push(Buffer::from(encoded.arrow_data));
arrow_data_len
} else {
0
};

Ok((aligned_size, body_len))
}

fn push_continuation_buffer(
out: &mut Vec<Buffer>,
write_options: &IpcWriteOptions,
total_len: i32,
) -> Result<(), ArrowError> {
// Continuation bytes are generated stream framing, so they need a small owned buffer.
let mut buffer = Vec::with_capacity(8);
write_continuation(&mut buffer, write_options, total_len)?;
out.push(Buffer::from(buffer));
Ok(())
}

fn push_padding_buffer(out: &mut Vec<Buffer>, len: usize) {
if len > 0 {
out.push(Buffer::from(&PADDING[..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.

🚀

Comment thread arrow-ipc/src/writer.rs
Comment on lines -2081 to -2170
let arrow_data_len = encoded.arrow_data.len();
if arrow_data_len % usize::from(write_options.alignment) != 0 {
return Err(ArrowError::MemoryError(
"Arrow data not aligned".to_string(),
));
}

let a = usize::from(write_options.alignment - 1);
let buffer = encoded.ipc_message;
let flatbuf_size = buffer.len();
let prefix_size = if write_options.write_legacy_ipc_format {
4
} else {
8
};
let aligned_size = (flatbuf_size + prefix_size + a) & !a;
let padding_bytes = aligned_size - flatbuf_size - prefix_size;

write_continuation(
&mut writer,
write_options,
(aligned_size - prefix_size) as i32,
)?;

// write the flatbuf
if flatbuf_size > 0 {
writer.write_all(&buffer)?;
}
// write padding
writer.write_all(&PADDING[..padding_bytes])?;

// write arrow data
let body_len = if arrow_data_len > 0 {
write_body_buffers(&mut writer, &encoded.arrow_data, write_options.alignment)?
} else {
0
};

Ok((aligned_size, body_len))
}

fn write_body_buffers<W: Write>(
mut writer: W,
data: &[u8],
alignment: u8,
) -> Result<usize, ArrowError> {
let len = data.len();
let pad_len = pad_to_alignment(alignment, len);
let total_len = len + pad_len;

// write body buffer
writer.write_all(data)?;
if pad_len > 0 {
writer.write_all(&PADDING[..pad_len])?;
}

Ok(total_len)
}

/// Write a record batch to the writer, writing the message size before the message
/// if the record batch is being written to a stream
fn write_continuation<W: Write>(
mut writer: W,
write_options: &IpcWriteOptions,
total_len: i32,
) -> Result<usize, ArrowError> {
let mut written = 8;

// the version of the writer determines whether continuation markers should be added
match write_options.metadata_version {
crate::MetadataVersion::V1 | crate::MetadataVersion::V2 | crate::MetadataVersion::V3 => {
unreachable!("Options with the metadata version cannot be created")
}
crate::MetadataVersion::V4 => {
if !write_options.write_legacy_ipc_format {
// v0.15.0 format
writer.write_all(&CONTINUATION_MARKER)?;
written = 4;
}
writer.write_all(&total_len.to_le_bytes()[..])?;
}
crate::MetadataVersion::V5 => {
// write continuation marker and message length
writer.write_all(&CONTINUATION_MARKER)?;
writer.write_all(&total_len.to_le_bytes()[..])?;
}
z => panic!("Unsupported crate::MetadataVersion {z:?}"),
};

Ok(written)

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.

nice!

Comment thread arrow-ipc/src/writer.rs
Comment on lines +150 to +160
fn write_vec(&mut self, bytes: Vec<u8>) -> Result<(), ArrowError> {
if bytes.is_empty() {
return Ok(());
}

match self {
Self::Writer(writer) => writer.write_all(&bytes)?,
Self::Buffers(out) => out.push(Buffer::from(bytes)),
}
Ok(())
}

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.

nice now callers dont need to handle this at each call site

Comment thread arrow-ipc/src/writer.rs
Ok(())
}

fn write_encoded_buffer(&mut self, buffer: EncodedBuffer) -> Result<(), ArrowError> {

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 a doc comment above this would be nice, otherwise it makes sense to me.

@Phoenix500526 Phoenix500526 Jul 18, 2026

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 added some doc comments to those methods that are mainly called from outside IpcMessageSink.

FYI:5cfcf8a

@Rich-T-kid

Copy link
Copy Markdown
Contributor

It would be nice to double check that we didnt accidntly slow down the StreamWriter as well.

@alamb could you please run the arrow-ipc benchmarks? Thank you 👍

Signed-off-by: Jiawei Zhao <Phoenix500526@163.com>
@Jefffrey

Copy link
Copy Markdown
Contributor

run benchmark ipc_writer

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5009419548-1137-4gwjg 6.12.85+ #1 SMP Mon May 11 08:17:35 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 issue/7812 (5cfcf8a) to 980667f (merge-base) diff
BENCH_NAME=ipc_writer
BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench ipc_writer
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                                                       issue_7812                             main
-----                                                       ----------                             ----
arrow_ipc_stream_writer/FileWriter/write_10                 1.09    102.3±0.72µs        ? ?/sec    1.00     94.1±2.89µs        ? ?/sec
arrow_ipc_stream_writer/FileWriter/write_10/dict/delta      1.02    154.4±3.09µs        ? ?/sec    1.00    151.7±3.40µs        ? ?/sec
arrow_ipc_stream_writer/StreamWriter/write_10               1.15    100.2±0.49µs        ? ?/sec    1.00     87.4±0.45µs        ? ?/sec
arrow_ipc_stream_writer/StreamWriter/write_10/dict          1.00     76.8±6.32µs        ? ?/sec    1.11     85.4±6.64µs        ? ?/sec
arrow_ipc_stream_writer/StreamWriter/write_10/dict/delta    1.02    148.3±3.12µs        ? ?/sec    1.00    144.8±3.08µs        ? ?/sec
arrow_ipc_stream_writer/StreamWriter/write_10/zstd          1.01      7.3±0.14ms        ? ?/sec    1.00      7.2±0.04ms        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 65.0s
Peak memory 11.7 MiB
Avg memory 10.0 MiB
CPU user 61.8s
CPU sys 0.0s
Peak spill 0 B

branch

Metric Value
Wall time 65.0s
Peak memory 12.4 MiB
Avg memory 9.8 MiB
CPU user 58.1s
CPU sys 0.0s
Peak spill 0 B

File an issue against this benchmark runner

@Rich-T-kid

Copy link
Copy Markdown
Contributor

looks to be mostly noise? its within +- 10. can we run it again to check if its reproducible

@Rich-T-kid Rich-T-kid left a comment

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.

LGTM @Phoenix500526

@Jefffrey I think this is ready for a review

Comment thread arrow-ipc/Cargo.toml
criterion = { workspace = true }
tempfile = "3.3"
tokio = "1.43.0"
tokio = { version = "1.43.0", features = ["io-util", "macros", "rt"] }

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.

Does this count as increasing our dependencies? Tokio was already imported, so I think this is fine

Comment thread arrow-ipc/src/writer.rs
}
}

/// Destination for a complete framed IPC message.

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.

we should also add benchmarks for the stream encoder to catch regressions in the future.

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 should be a follow up so that its easier to review. I created this issue to track it #10373

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.

arrow-ipc StreamWriter better ergonomics with async

4 participants