/** * Caching utilities for the TVM web runtime. * * Provides a generic LRUCache and a CacheState container that manages * domain-specific caches used by the WebGPU runtime. */ import { Disposable } from "./types"; /** * A generic LRU (Least Recently Used) cache with bounded size. * * Entries are evicted in insertion order when the cache exceeds `maxSize`. * Uses a Map to maintain insertion order for O(1) LRU eviction. * * @typeParam K - Cache key type. * @typeParam V - Cache value type. */ export declare class LRUCache { private cache; private readonly maxSize; /** Optional callback invoked when an entry is evicted. */ private readonly onEvict?; constructor(maxSize: number, onEvict?: (key: K, value: V) => void); /** * Get a value from the cache, constructing it via `constructor` on miss. * * On hit: moves the entry to most-recently-used position and returns it. * On miss: calls `constructor()` to create the value, inserts it, and * returns it. If the cache is full, the least-recently-used entry is * evicted first. * * @param key The cache key. * @param constructor Factory function called on cache miss to produce the value. * @returns The cached or newly constructed value. */ get(key: K, constructor: () => V): V; /** * Check whether eviction would be needed for a new entry. * * Useful when the caller needs to perform side effects before eviction * (e.g. flushing pending GPU commands before destroying an evicted buffer). * * @param key The key to check. * @returns true if inserting `key` would trigger eviction of another entry. */ needEviction(key: K): boolean; /** * Clear all cached entries. * * Does not dispose values — the caller is responsible for cleanup * (e.g. destroying GPU buffers) before calling invalidate. */ invalidate(): void; /** Number of entries currently in the cache. */ get size(): number; /** Iterate over all cached values (for disposal). */ values(): IterableIterator; } /** * CacheState manages domain-specific caches for the WebGPU runtime. * * Currently contains: * - **shapeCache**: Caches TVM ShapeTuple objects keyed by dimension string. * - Why: `makeShapeTuple()` is called on every tensor operation, crossing * the JS→WASM FFI boundary each time. During LLM decode, the same shapes * repeat every token (e.g. [1,32,128]), so caching avoids thousands of * redundant FFI round-trips. * - Invalidation: Cache entries may be evicted, but returned shape tuples * hold independent references and remain valid for their caller's scope. * * Future additions (follow-up PR): * - **uniformCache**: Caches GPU uniform buffers keyed by content hash. * - Why: Many dispatches use identical scalar arguments (matrix dims, etc.). * Reusing the buffer avoids `createBuffer` + `writeBuffer` overhead. * - Invalidation: Must invalidate on any GPU buffer deallocation, since * buffer pointers can be reused by the allocator, making cached entries * that reference the old buffer stale. */ export declare class CacheState { /** * Cache for TVM ShapeTuple objects. * * Key: comma-separated dimension string, e.g. "1,32,128" * Value: TVM ShapeTuple object (Disposable) * * Eviction releases only the cache's reference. Shape tuples returned to * callers have independent references and normal scope-managed lifetimes. */ readonly shapeCache: LRUCache; constructor(shapeCacheSize?: number); /** * Compute the cache key for a shape tuple. * * @param shape Array of dimension values. * @returns String key suitable for shapeCache lookup. */ static computeShapeKey(shape: Array): string; /** * Dispose all cached objects and clear all caches. */ dispose(): void; }