Skip to content

Commit 1850cab

Browse files
authored
Replace Kanal with async-channel (#11040)
Use async-channel for bounded writer pipelines, runtime dispatch, and CUDA completion notifications. Consume receivers as streams directly and remove the unused channel adapter. Preserve queue capacities and use nonblocking sends for unbounded dispatch and single-shot completion callbacks. --------- Signed-off-by: Nicholas Gates <nick@nickgates.com>
1 parent d197efd commit 1850cab

17 files changed

Lines changed: 95 additions & 107 deletions

File tree

‎Cargo.lock‎

Lines changed: 4 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ arrow-ipc = "59.2"
112112
arrow-row = "59.2"
113113
arrow-schema = "59.2"
114114
arrow-select = "59.2"
115+
async-channel = "2.5.0"
115116
async-executor = "1.14.0"
116117
async-fs = "2.2.0"
117118
async-lock = "3.4"
@@ -184,7 +185,6 @@ inventory = "0.3.20"
184185
itertools = "0.14.0"
185186
jiff = "0.2.28"
186187
jni = { version = "0.22.0" }
187-
kanal = "0.1.1"
188188
lasso = { version = "0.7", features = ["multi-threaded", "inline-more"] }
189189
lending-iterator = "0.1.7"
190190
libfuzzer-sys = "0.4"

‎vortex-cuda/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ _test-harness = []
2222

2323
[dependencies]
2424
arrow-schema = { workspace = true, features = ["ffi"] }
25+
async-channel = { workspace = true }
2526
async-trait = { workspace = true }
2627
futures = { workspace = true, features = ["executor"] }
2728
itertools = { workspace = true }
28-
kanal = { workspace = true }
2929
memmap2 = { workspace = true }
3030
num-traits = { workspace = true }
3131
object_store = { workspace = true, features = ["fs"] }

‎vortex-cuda/src/stream.rs‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ use std::mem::size_of_val;
99
use std::ops::Deref;
1010
use std::sync::Arc;
1111

12+
use async_channel::Receiver;
13+
use async_channel::Sender;
1214
use futures::future::BoxFuture;
13-
use kanal::Sender;
1415
use tracing::warn;
1516
use vortex::array::buffer::BufferHandle;
1617
use vortex::error::VortexResult;
@@ -221,8 +222,8 @@ pub(crate) async fn await_stream_callback(stream: &CudaStream) -> VortexResult<(
221222
/// # Errors
222223
///
223224
/// Returns an error if registering the host callback function fails.
224-
fn register_stream_callback(stream: &CudaStream) -> VortexResult<kanal::AsyncReceiver<()>> {
225-
let (tx, rx) = kanal::bounded::<()>(1);
225+
fn register_stream_callback(stream: &CudaStream) -> VortexResult<Receiver<()>> {
226+
let (tx, rx) = async_channel::bounded::<()>(1);
226227

227228
let tx_ptr = Box::into_raw(Box::new(tx));
228229

@@ -237,10 +238,10 @@ fn register_stream_callback(stream: &CudaStream) -> VortexResult<kanal::AsyncRec
237238
// before. We have unique ownership and can therefore free it.
238239
let tx = unsafe { Box::from_raw(user_data as *mut Sender<()>) };
239240

240-
// Blocking send as we're in a callback invoked by the CUDA driver.
241+
// The callback sends once into an empty capacity-one channel.
241242
// NOTE: send can fail if the CudaEvent is dropped by the caller, in which case the receiver
242243
// is closed and sends will fail.
243-
if let Err(_e) = tx.send(()) {
244+
if let Err(_e) = tx.try_send(()) {
244245
warn!(error = ?_e, "register_stream_callback send failed due to error");
245246
}
246247
}
@@ -263,7 +264,7 @@ fn register_stream_callback(stream: &CudaStream) -> VortexResult<kanal::AsyncRec
263264
})?;
264265
}
265266

266-
Ok(rx.to_async())
267+
Ok(rx)
267268
}
268269

269270
#[cfg(test)]

‎vortex-file/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ all-features = true
1717
[dependencies]
1818
arrow-array = { workspace = true }
1919
arrow-schema = { workspace = true }
20+
async-channel = { workspace = true }
2021
async-trait = { workspace = true }
2122
bytes = { workspace = true }
2223
flatbuffers = { workspace = true }
2324
futures = { workspace = true, features = ["std", "async-await"] }
2425
itertools = { workspace = true }
25-
kanal = { workspace = true }
2626
moka = { workspace = true, features = ["sync"] }
2727
object_store = { workspace = true, optional = true }
2828
parking_lot = { workspace = true }

‎vortex-file/src/segments/writer.rs‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::sync::Arc;
55
use std::sync::atomic::AtomicU64;
66
use std::sync::atomic::Ordering;
77

8+
use async_channel::Sender;
89
use async_trait::async_trait;
910
use parking_lot::Mutex;
1011
use vortex_buffer::Alignment;
@@ -18,13 +19,13 @@ use vortex_layout::sequence::SequenceId;
1819
use crate::footer::SegmentSpec;
1920

2021
pub struct BufferedSegmentSink {
21-
buffers: kanal::AsyncSender<ByteBuffer>,
22+
buffers: Sender<ByteBuffer>,
2223
byte_offset: AtomicU64,
2324
segment_specs: Mutex<Vec<SegmentSpec>>,
2425
}
2526

2627
impl BufferedSegmentSink {
27-
pub fn new(send: kanal::AsyncSender<ByteBuffer>, byte_offset: u64) -> Self {
28+
pub fn new(send: Sender<ByteBuffer>, byte_offset: u64) -> Self {
2829
Self {
2930
buffers: send,
3031
byte_offset: AtomicU64::new(byte_offset),
@@ -90,10 +91,10 @@ impl SegmentSink for BufferedSegmentSink {
9091
};
9192

9293
if let Some(padding) = padding_buffer {
93-
let _ = self.buffers.send(padding).await;
94+
drop(self.buffers.send(padding).await);
9495
}
9596
for buffer in buffers {
96-
let _ = self.buffers.send(buffer).await;
97+
drop(self.buffers.send(buffer).await);
9798
}
9899

99100
Ok(segment_id)

‎vortex-file/src/writer.rs‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use std::sync::Arc;
77
use std::sync::atomic::AtomicU64;
88
use std::sync::atomic::Ordering;
99

10+
use async_channel::SendError;
11+
use async_channel::Sender;
12+
use async_channel::bounded;
1013
use futures::FutureExt;
1114
use futures::StreamExt;
1215
use futures::TryStreamExt;
@@ -40,7 +43,6 @@ use vortex_error::vortex_bail;
4043
use vortex_error::vortex_err;
4144
use vortex_io::IoBuf;
4245
use vortex_io::VortexWrite;
43-
use vortex_io::kanal_ext::KanalExt;
4446
use vortex_io::runtime::BlockingRuntime;
4547
use vortex_io::session::RuntimeSessionExt;
4648
use vortex_layout::BufferedBytesTracker;
@@ -332,7 +334,7 @@ impl VortexWriteOptions {
332334
let mut position = MAGIC_BYTES.len() as u64;
333335

334336
// Create a channel to send buffers from the segment sink to the output stream.
335-
let (send, recv) = kanal::bounded_async(1);
337+
let (send, recv_stream) = bounded(1);
336338

337339
let segments = Arc::new(BufferedSegmentSink::new(send, position));
338340

@@ -354,7 +356,6 @@ impl VortexWriteOptions {
354356
});
355357

356358
// Flush buffers as they arrive
357-
let recv_stream = recv.into_stream();
358359
pin_mut!(recv_stream);
359360
while let Some(buffer) = recv_stream.next().await {
360361
if buffer.is_empty() {
@@ -420,10 +421,9 @@ impl VortexWriteOptions {
420421
/// flush remaining buffers, and receive the [`WriteSummary`].
421422
pub fn writer<'w, W: VortexWrite + Unpin + 'w>(self, write: W, dtype: DType) -> Writer<'w> {
422423
// Create a channel for sending arrays to the layout task.
423-
let (arrays_send, arrays_recv) = kanal::bounded_async(1);
424+
let (arrays_send, arrays_recv) = bounded(1);
424425

425-
let arrays =
426-
ArrayStreamExt::boxed(ArrayStreamAdapter::new(dtype, arrays_recv.into_stream()));
426+
let arrays = ArrayStreamExt::boxed(ArrayStreamAdapter::new(dtype, arrays_recv));
427427

428428
let write = CountingVortexWrite::new(write);
429429
let bytes_written = write.counter();
@@ -571,7 +571,7 @@ fn validate_metadata_segments(metadata: &HashMap<String, ByteBuffer>) -> VortexR
571571
/// An async API for writing Vortex files.
572572
pub struct Writer<'w> {
573573
// The input channel for sending arrays to the writer.
574-
arrays: Option<kanal::AsyncSender<VortexResult<ArrayRef>>>,
574+
arrays: Option<Sender<VortexResult<ArrayRef>>>,
575575
// The writer task that ultimately produces the footer.
576576
future: Fuse<LocalBoxFuture<'w, VortexResult<WriteSummary>>>,
577577
// The bytes written so far.
@@ -620,7 +620,7 @@ impl Writer<'_> {
620620
while let Some(chunk) = stream.next().await {
621621
arrays.send(chunk).await?;
622622
}
623-
Ok::<_, kanal::SendError>(())
623+
Ok::<_, SendError<VortexResult<ArrayRef>>>(())
624624
}
625625
.fuse();
626626
pin_mut!(stream_fut);

‎vortex-io/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ version = { workspace = true }
1616
all-features = true
1717

1818
[dependencies]
19+
async-channel = { workspace = true }
1920
async-executor = { workspace = true }
2021
async-fs = { workspace = true }
2122
async-stream = { workspace = true }
@@ -24,7 +25,6 @@ bytes = { workspace = true }
2425
crossbeam-channel = { workspace = true }
2526
futures = { workspace = true, features = ["std", "executor"] }
2627
glob = { workspace = true }
27-
kanal = { workspace = true }
2828
object_store = { workspace = true, optional = true, features = ["fs"] }
2929
parking_lot = { workspace = true }
3030
pin-project-lite = { workspace = true }

‎vortex-io/src/kanal_ext.rs‎

Lines changed: 0 additions & 22 deletions
This file was deleted.

‎vortex-io/src/lib.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub use write::*;
1818
pub mod compat;
1919
pub mod filesystem;
2020
mod io_buf;
21-
pub mod kanal_ext;
2221
mod limit;
2322
#[cfg(feature = "object_store")]
2423
pub mod object_store;

0 commit comments

Comments
 (0)