Skip to main content

FactsCache

Struct FactsCache 

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

A bounded cache of key projections, sized off the same max_keys as the StatsTable it shadows, counting what the bound costs (RFC 09 §5.1 O6).

Why this exists (issue #107). Projecting a key is not free — a KeyFacts owns a String per subject chunk plus the resolved SubjectFacts — so every observer caches it, and zengui’s cache was a plain HashMap that grew one entry per distinct key ever seen. The engine’s key table is bounded and counts its evictions; the projection cache shadowing it was, in stats.rs’s own words, “merely a leak with better manners”.

Why an LRU and not “prune to the stats table”, which is the obvious fix:

  • the table is fed from samples, and an observer also projects liveliness token keys, which never enter it. Pruning to the table would delete and re-project those on every tick, and drop them from any “keys seen” list;
  • a frontend holds a key-tree snapshot, not a key list, so membership means walking the tree per tick — O(n) allocation on the render thread at up to 50k keys, where this is O(1) amortised on the insert path;
  • “evicted because the table evicted it” and “evicted because it was never in the table” are different facts, and one counter over both is exactly what O6 forbids.

Recency is last-observed, not last-rendered, which is what keeps get a pure read: a &self render path can look keys up without touching the ordering, so no interior mutability and no signature churn in the views.

The bound and the batch eviction are BoundedLru’s — shared with the StatsTable this shadows, which is where the argument for both was written. The ledger stays here: inserted / evicted are this cache’s own facts, not the table’s (O6).

Implementations§

Source§

impl FactsCache

Source

pub fn with_capacity(max_keys: usize) -> FactsCache

A cache bounded at max_keys projections. Pass the same bound the stats table was built with: the cache cannot usefully outgrow the table it shadows, and one number makes that one sentence.

Source

pub fn ensure(&mut self, base: &str, key: &str, slices: Option<&SliceSet>)

Project key if it is not cached yet; bump its recency either way.

The single insert point — the whole bound rests on that being true.

Source

pub fn get(&self, key: &str) -> Option<&KeyFacts>

A cached projection, if it is still held. Pure: recency is not touched, so this is safe to call from a &self render path.

Source

pub fn keys(&self) -> impl Iterator<Item = &str>

Source

pub fn iter(&self) -> impl Iterator<Item = (&str, &KeyFacts)>

Every held projection, keyed. Unordered (the map is a HashMap) — callers that need determinism collect into an ordered structure, which is what both doctor and field context builders do.

Source

pub fn len(&self) -> usize

Source

pub fn is_empty(&self) -> bool

Source

pub fn max_keys(&self) -> usize

Source

pub fn evicted(&self) -> u64

Projections retired to stay within the bound.

Displayed, never hidden: a cache that stopped growing and a bus that went quiet look identical from the outside (RFC 09 §5.1 O6).

Source

pub fn inserted(&self) -> u64

Projections made since the last clear.

The other half of the O6 ledger, and the reason it is a public number rather than an internal one: inserted == len() + evicted() is the conservation law, and without this counter it cannot be checked from outside. Note it counts insertions, not distinct keys — a key evicted and later re-observed is projected again, which is precisely the cost the bound is trading against.

Source

pub fn resolve_all(&mut self, slices: &SliceSet)

Re-resolve every held projection against a newly-loaded slice set — what a registry arriving after the first samples calls for.

Source

pub fn clear(&mut self)

Base change / reconnect / context switch. Keeps the bound and resets the counter: retirements under another deployment are not this one’s.

Trait Implementations§

Source§

impl Debug for FactsCache

Source§

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

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

impl Default for FactsCache

Source§

fn default() -> Self

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

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<Source> AccessAs for Source

Source§

fn ref_as<T>(&self) -> <Source as IGuardRef<T>>::Guard<'_>
where Source: IGuardRef<T>, T: ?Sized,

Provides immutable access to a type as if it were its ABI-unstable equivalent.
Source§

fn mut_as<T>(&mut self) -> <Source as IGuardMut<T>>::GuardMut<'_>
where Source: IGuardMut<T>, T: ?Sized,

Provides mutable access to a type as if it were its ABI-unstable equivalent.
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> AsNode<T> for T

Source§

fn as_node(&self) -> &T

Source§

impl<T> AsNodeMut<T> for T

Source§

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

Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, As> IGuardMut<As> for T
where T: Into<As>, As: Into<T>,

Source§

type GuardMut<'a> = MutAs<'a, T, As> where T: 'a

The type of the guard which will clean up the temporary after applying its changes to the original.
Source§

fn guard_mut_inner(&mut self) -> <T as IGuardMut<As>>::GuardMut<'_>

Construct the temporary and guard it through a mutable reference.
Source§

impl<T, As> IGuardRef<As> for T
where T: Into<As>, As: Into<T>,

Source§

type Guard<'a> = RefAs<'a, T, As> where T: 'a

The type of the guard which will clean up the temporary.
Source§

fn guard_ref_inner(&self) -> <T as IGuardRef<As>>::Guard<'_>

Construct the temporary and guard it through an immutable reference.
Source§

impl<T> Includes<End> for T

Source§

type Output = End

The result
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<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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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 = !

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