Skip to main content

ResourceTracker

Struct ResourceTracker 

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

A resource tracker that enforces configurable limits.

Checks allocator-backed memory usage and tracks execution time, returning errors when limits are exceeded. It also schedules garbage collection.

Uses Cell for mutable timing and recursion state behind shared references.

max_duration limits cumulative execution time: the clock runs only while the VM is executing bytecode (between the outermost on_execution_start/on_execution_stop pair) and is paused while execution is suspended waiting on the host — external function calls, OS callbacks — and between REPL feeds. The accumulated time is serialized, so a deserialized session resumes its budget where it left off rather than restarting from zero.

Implementations§

Source§

impl ResourceTracker

Source

pub fn new(limits: ResourceLimits) -> Self

Creates a new ResourceTracker with the given limits.

The execution-time clock starts at zero and only runs while the VM executes, so the tracker can be created any amount of time before the first run without consuming the duration budget. A configured max_memory requires monty-alloc installed as the global allocator and armed via its set_limit; otherwise it is silently not enforced.

Source

pub fn elapsed(&self) -> Duration

Returns the cumulative execution time: bytecode-execution wall time accumulated across runs/feeds, excluding time suspended on the host or idle between feeds. Includes the in-progress window if the VM is currently executing.

Source

pub fn max_duration(&self) -> Option<Duration>

Returns the configured maximum cumulative execution time, if any.

Source

pub fn max_memory(&self) -> Option<usize>

Returns the configured memory budget, if any. Hosts that bound a worker process from outside the interpreter size that bound from this.

Source

pub fn set_max_duration(&mut self, duration: Duration)

Sets the maximum execution duration as a fresh budget from now, resetting the accumulated execution time to zero.

This lets a host enforce a different (typically shorter) time limit for a resumed phase — e.g. allowing a long build phase, then giving repr() of the result only a few milliseconds. Time spent suspended in the host never counts toward the budget either way.

Source

pub fn check_allocation(&self, additional: usize) -> Result<(), ResourceError>

Checks whether one up-front allocation fits the memory budget.

Use this before reserving a buffer that could cross both the soft and hard allocator limits before execution reaches another checkpoint.

Source

pub fn check_time(&self) -> Result<(), ResourceError>

Called periodically to check time and allocator-backed memory limits.

Returns Ok(()) while configured limits are respected, or the relevant resource error once either limit is exceeded.

Takes &self rather than &mut self because checking elapsed time is a read-only operation. This allows time checks in contexts that only have an immutable heap reference, such as py_repr_fmt.

Source

pub fn check_recursion_depth( &self, current_depth: usize, ) -> Result<(), ResourceError>

Called before pushing a new call frame to check recursion depth.

Returns Ok(()) if within recursion limit, or Err(ResourceError::Recursion) if the limit would be exceeded. current_depth is the call stack depth before the new frame is pushed.

Source

pub fn check_large_result( &self, estimated_bytes: usize, ) -> Result<(), ResourceError>

Called before operations that may produce large results (>100KB).

This allows pre-emptive rejection of operations like 2 ** 10_000_000 before the memory is actually allocated. The check only happens for estimated result sizes above LARGE_RESULT_THRESHOLD to avoid overhead on small operations.

Source

pub fn gc_interval(&self) -> Option<usize>

Returns the configured garbage collection interval, in GC-tracked allocations.

The cycle collector runs at most once per gc_interval GC-tracked allocations, and additionally short-circuits when no cycle candidates are pending — so programs that never form cycles pay no collector cost regardless of their allocation rate. None tells the heap to use its built-in default scheduling threshold.

Source

pub fn on_execution_start(&self)

Called when the VM enters its execution loop from a host boundary (VM::run_external), starting one execution window.

Paired with on_execution_stop and never nested — VM-internal re-entry (task switches, host-initiated function evaluation) uses the raw run loop, so its time falls inside the enclosing window. The execution-time clock runs between the pair; it is not running while execution is suspended waiting on the host (external function calls) or between feeds.

Source

pub fn on_execution_stop(&self)

Called when the VM leaves its execution loop — on completion, error, or suspension at an external call. See on_execution_start.

Trait Implementations§

Source§

impl Debug for ResourceTracker

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ResourceTracker

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for ResourceTracker

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for ResourceTracker

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. 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> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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, 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.