Skip to main content

ModelCache

Struct ModelCache 

Source
pub struct ModelCache { /* private fields */ }
Expand description

Multi-model cache with LRU eviction under VRAM pressure.

Invariants:

  • At most one engine has residency == Gpu at a time (single-GPU inference).
  • lru_order tracks all entries from least-recently-used (front) to most-recently-used (back).
  • max_cached limits total entries across both residency states (Gpu and Parked).
  • in_flight holds names temporarily checked out via take() until they are returned via restore(). Such names are physically absent from entries/lru_order but logically still part of the cache for the purposes of contains() and snapshot() — without this, a parallel reader during a take window would mistakenly conclude the model is uncached.

Implementations§

Source§

impl ModelCache

Source

pub fn new(max_cached: usize) -> Self

Source

pub fn insert( &mut self, engine: Box<dyn InferenceEngine>, vram_bytes: u64, ) -> Option<Box<dyn InferenceEngine>>

Insert an engine into the cache. If the cache is full, the LRU entry is dropped entirely. Returns the evicted engine (if any) for cleanup.

Source

pub fn get(&self, model_name: &str) -> Option<&CachedEngine>

Get a reference to a cached engine entry (does not update LRU order).

Source

pub fn get_mut(&mut self, model_name: &str) -> Option<&mut CachedEngine>

Get a mutable reference to the engine for a model, if cached.

Source

pub fn take(&mut self, model_name: &str) -> Option<CachedEngine>

Remove an engine from the cache, returning the full entry. Used by the take-and-restore pattern: remove before inference, re-insert after. While the engine is checked out, the name remains in in_flight so parallel readers (contains, snapshot, cached_model_names) still see the model as logically cached.

Source

pub fn restore(&mut self, cached: CachedEngine)

Re-insert a taken engine after inference completes.

Source

pub fn clear_in_flight(&mut self, model_name: &str)

Clear an in-flight marker without restoring an engine. Called when the take-and-restore window terminates abnormally (JoinError, panic that escapes catch_unwind, etc.) and we have no engine to put back — otherwise the name leaks into in_flight forever, making contains() permanently lie to ensure_model_ready while take()/get() keep returning None.

Source

pub fn insert_loaded( &mut self, model_name: String, engine: Box<dyn InferenceEngine>, vram_bytes: u64, ) -> Option<Box<dyn InferenceEngine>>

Insert a loaded engine with a known VRAM footprint. Unlike insert(), this takes a name separately from the engine.

Source

pub fn contains(&self, model_name: &str) -> bool

Check if a model is in the cache. Treats names taken-but-not-restored as still cached so concurrent readers don’t see a transient hole during a take/restore window.

Source

pub fn remove(&mut self, model_name: &str) -> Option<Box<dyn InferenceEngine>>

Remove a model from the cache entirely, returning its engine. Also clears the name from in_flight so we never claim a model is cached after explicit removal.

Source

pub fn unload_all(&mut self) -> Vec<String>

Unload all models from GPU. Returns names of models that were unloaded. Each is transitioned to Parked (retain tokenizers/caches for faster reload).

Source

pub fn unload_active(&mut self) -> Option<String>

Unload the current GPU-resident model (if any) to make room for a new one. The engine is parked (retains tokenizers/caches) for faster reload. Returns the name of the unloaded model.

Source

pub fn clear(&mut self) -> Vec<Box<dyn InferenceEngine>>

Drop all entries, returning all engines for cleanup. Also clears in_flight — any caller still holding a checked-out engine must drop it on their own (they own that CachedEngine); we just stop claiming it’s logically present.

Source

pub fn active_vram_bytes(&self) -> u64

VRAM footprint of the currently GPU-resident model (0 if none loaded).

Source

pub fn active_model(&self) -> Option<&str>

The currently GPU-loaded model name.

Source

pub fn cached_model_names(&self) -> Vec<String>

All cached model names (any residency, including names temporarily taken-out for in-flight inference).

Source

pub fn snapshot(&self) -> EngineSnapshot

Snapshot of the cache’s current state — what /api/models and /api/status report. Derived directly from the cache so there’s no parallel field that can drift. During a take/restore window the engine that was GPU-resident is reflected via in_flight_active so readers don’t see a transient “no model loaded” hole.

Source

pub fn len(&self) -> usize

Number of cached entries.

Source

pub fn is_empty(&self) -> bool

Source

pub fn evict_idle( &mut self, ttl: Duration, ) -> Vec<(String, Box<dyn InferenceEngine>)>

Reclaim cache entries whose last_used is older than ttl. Only entries that are not GPU-resident are eligible — the active model is always preserved. Skipped entirely when the cache holds at most one entry (so we never tear down the only warm engine after a quiet period).

Returns evicted (name, engine) pairs so callers can drop the engines outside any cache mutex — cuMemFree and safetensor unmap on drop can block other cache users for non-trivial time.

Source

pub fn evict_lru_parked_except( &mut self, skip: Option<&str>, ) -> Option<(String, Box<dyn InferenceEngine>)>

Evict the LRU entry that is not GPU-resident and (optionally) not the named model. Returns (name, engine) so the caller can drop the engine outside the cache lock and then issue any GPU reclamation.

Used by the load-time evict-to-fit recovery path: when a fresh load’s preflight fails, we shrink the parked working set one entry at a time and retry. The skip parameter exists because the parked-reload branch must not evict the very entry it’s about to reload.

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> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

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

Initializes a with the given initializer. Read more
Source§

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

Dereferences the given pointer. Read more
Source§

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

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

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

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + 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
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + 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> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

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

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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