Skip to main content

EmbedPool

Struct EmbedPool 

Source
pub struct EmbedPool {
    tx: Sender<EmbedRequest>,
    live_workers: Arc<AtomicUsize>,
    loaded_workers: Arc<AtomicUsize>,
    model_rss_per_worker_bytes: Arc<AtomicUsize>,
    engine_propagation_tx: Option<Sender<(usize, usize)>>,
}
Expand description

Async handle to the embedding worker thread pool.

Wraps a bounded mpsc channel shared by n spawn_blocking worker threads. Each worker owns its own ORT session and tokenizer; the pool dispatches EmbedRequest variants to whichever worker is free next.

Clone is cheap — the underlying channel sender and atomic counters are reference-counted.

Fields§

§tx: Sender<EmbedRequest>§live_workers: Arc<AtomicUsize>§loaded_workers: Arc<AtomicUsize>

Number of workers that currently have model instances loaded in memory.

§model_rss_per_worker_bytes: Arc<AtomicUsize>

Median RSS delta (bytes) measured across all workers during sequential model load.

Workers load one at a time (leader first, then followers in sequence). Each reports its own RSS before/after load_models() via ready_tx. The pool stores the median once all workers have signaled ready — robust to one outlier from page-cache settling or ORT arena init jitter.

Used by run_readiness_probe to correctly deduct the model-weight footprint from the available workspace before computing per-worker budget. Returns 0 on non-Linux targets where RSS measurement is unavailable, or before the init task has completed.

§engine_propagation_tx: Option<Sender<(usize, usize)>>

Broadcast sender for cross-worker TRT engine cache propagation.

When Some, after any worker writes a new engine plan to EFS, a (batch, seq) shape notification is broadcast to every subscribed worker so they eagerly run trt_prewarm (~1-3s fast disk-load) instead of paying full JIT cost on the next real request. None when BGE_M3_ENGINE_PROPAGATION_ENABLED=0.

Implementations§

Source§

impl EmbedPool

Source

pub fn broadcast_engine_ready(&self, shape: (usize, usize))

Broadcasts a (batch, seq) shape notification to all subscribed peer workers, signaling that the TRT engine plan for this shape is now on EFS.

Workers receive the notification in their main loop drain and run trt_prewarm against their own session for a ~1-3s fast disk-load rather than paying full JIT cost on the next real request for this shape.

send returns Err only when there are zero subscribers (all workers gone). This is non-fatal; the engine plan is still on EFS.

Source

pub fn spawn( n: usize, cache_dir: PathBuf, config: WorkerConfig, ) -> (Self, JoinHandle<Result<()>>)

Spawns n embedding worker threads and returns the pool plus an init handle that resolves once all workers have finished loading their models.

When a GPU execution provider (cuda or tensorrt) is selected, n is clamped to config.gpu_count: each worker is pinned to a distinct CUDA device (device_id = worker_index % gpu_count). For TRT, the full warmup shape list is sharded across workers via a stride partition so each GPU compiles a disjoint subset in parallel, then shares the results via the EFS engine cache.

Source

pub async fn dense( &self, texts: Vec<String>, ) -> Result<(Vec<Vec<f32>>, EmbedStats)>

Runs dense (float32) embedding inference on texts.

§Errors
  • Returns Err if the worker channel has closed (pool shut down).
  • Returns Err if the worker drops the reply sender before responding.
  • Returns Err if the ORT session fails during inference.
Source

pub async fn sparse( &self, texts: Vec<String>, ) -> Result<(Vec<SparseEmbedding>, EmbedStats)>

Runs sparse (SPLADE-style) embedding inference on texts.

§Errors
  • Returns Err if the worker channel has closed (pool shut down).
  • Returns Err if the worker drops the reply sender before responding.
  • Returns Err if the ORT session fails during inference.
Source

pub async fn both( &self, texts: Vec<String>, ) -> Result<(Vec<DualEmbedding>, EmbedStats)>

Runs a single forward pass that yields both dense and sparse embeddings.

Equivalent to calling Self::dense and Self::sparse back-to-back, but uses one session.run() per chunk instead of two — at near-zero marginal GPU cost.

§Errors
  • Returns Err if the worker channel has closed (pool shut down).
  • Returns Err if the worker drops the reply sender before responding.
  • Returns Err if the ORT session fails during inference.
Source

pub(crate) async fn probe(&self, texts: Vec<String>) -> Result<ProbeResult>

Sends a probe request to a single worker and returns the result. Only called during init before ready is set.

Source

pub fn live_worker_count(&self) -> usize

Returns the number of worker threads currently alive (not yet exited).

Source

pub fn loaded_worker_count(&self) -> usize

Returns the number of workers that currently have model instances loaded in memory.

A worker transitions from loaded to unloaded after the crate::config::Config::idle_timeout elapses with no incoming requests, and back to loaded on the next request.

Source

pub fn queue_depth(&self) -> usize

Returns the number of requests currently queued but not yet picked up by a worker. Uses the channel’s current vs max capacity.

Source

pub fn model_rss_per_worker_bytes(&self) -> usize

Returns the median RSS delta (bytes) measured across all workers during sequential model load.

This is the per-worker model-weight footprint used by run_readiness_probe to compute the per-worker workspace budget. Returns 0 on non-Linux targets where RSS measurement is unavailable, or before the init task has completed.

Source

pub async fn send_adaptive_warmup( &self, batch: usize, seq: usize, ack: Sender<Result<u64>>, ) -> Result<(), ()>

Sends an adaptive warmup request to an available worker.

The worker calls trt_prewarm for (batch, seq) and replies on ack with the compile duration in milliseconds, or an error on failure. On non-TRT workers the reply is Ok(0) immediately.

§Errors

Returns Err(()) if the worker channel has closed (pool shut down).

Source

pub fn live_workers_for_shutdown(&self) -> Arc<AtomicUsize>

Returns a clone of the Arc<AtomicUsize> backing live_worker_count.

Used by the warmup-only path in lib.rs to poll worker exit progress AFTER the EmbedPool itself has been dropped. Dropping the pool closes the request channel, which signals workers to break out of their receive loops and drop their ORT sessions; the live counter is the only readable signal that those drop paths have completed.

Returning a clone of the raw Arc (rather than a snapshot) lets the caller hold a reference across the drop boundary without having to keep the pool’s other state alive.

Trait Implementations§

Source§

impl Clone for EmbedPool

Source§

fn clone(&self) -> EmbedPool

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FromRef<T> for T
where T: Clone,

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more