pub struct SampleAllocator { /* private fields */ }Expand description
Builds dora-owned output samples without borrowing the node.
§Why this exists (dora-rs/dora#2742)
An operator runs on its own thread and hands its outputs to the runtime’s
event loop. If what crosses that boundary is an Arrow array whose buffers
belong to the operator’s language runtime — a pyarrow array wrapping a
numpy buffer, say — then the runtime ends up freeing them. Releasing a
numpy-backed buffer acquires the Python GIL (pyarrow’s NumPyBuffer
destructor does PyAcquireGIL), so the runtime’s event loop blocks for as
long as the operator holds the GIL. That made a node unable to observe
Stop, and the daemon force-killed it at the grace period.
Handing the operator thread an allocator instead lets it encode into memory dora owns and release its own payload while it still holds the GIL. It is not an extra copy: the IPC encode is the same single copy the node would otherwise have made, just performed on the other side of the channel.
Implementations§
Source§impl SampleAllocator
impl SampleAllocator
Sourcepub fn allocate(&self, data_len: usize) -> NodeResult<DataSample>
pub fn allocate(&self, data_len: usize) -> NodeResult<DataSample>
Allocates a DataSample of the specified size.
For payloads at or above the zero-copy threshold the buffer is allocated
directly from the zenoh SHM provider (when available), so the producer
writes straight into shared memory and publishing moves the buffer into
zenoh’s put without a further copy. Smaller payloads — or the case
where no SHM provider exists (interactive/testing mode) — use a
heap-allocated, 128-byte-aligned buffer; the SHM provider is
page-aligned, so dedicating a full page to a small message is pure waste.
Sourcepub fn encode_arrow(&self, array: &DoraArray) -> NodeResult<EncodedSample>
pub fn encode_arrow(&self, array: &DoraArray) -> NodeResult<EncodedSample>
Encodes array as a complete Arrow IPC stream into a freshly allocated
sample. Uses the hand-rolled 1-copy fast path when the array type is
eligible, falling back to the official writer (one extra copy) otherwise.
The returned sample shares no memory with array, so the caller may —
and, when the payload is owned by a foreign runtime, must — drop
array on its own thread rather than let it travel to the node.
Trait Implementations§
Source§impl Clone for SampleAllocator
impl Clone for SampleAllocator
Source§fn clone(&self) -> SampleAllocator
fn clone(&self) -> SampleAllocator
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for SampleAllocator
impl RefUnwindSafe for SampleAllocator
impl Send for SampleAllocator
impl Sync for SampleAllocator
impl Unpin for SampleAllocator
impl UnsafeUnpin for SampleAllocator
impl UnwindSafe for SampleAllocator
Blanket Implementations§
Source§impl<Source> AccessAs for Source
impl<Source> AccessAs for Source
impl<T> Allocation for T
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request