Skip to main content

Module render_cache

Module render_cache 

Source
Expand description

Process-wide ceiling for the page render caches (READ_CACHE_BOUNDED).

Provides render_cache::budget, render_cache::set_budget, render_cache::resident_bytes, render_cache::enforce and render_cache::clear. Since 0.33 the render caches are bounded by default (render_cache::DEFAULT_BUDGET, 256 MiB); set_budget(usize::MAX) restores the unbounded behaviour of earlier releases. Process-wide ceiling for the page render caches.

Rendering a page memoises what it decoded — the wavelet background, the JB2 mask, the converted RGB pixmaps, the composited tiles (see [crate::djvu_render::PageLayers]). That makes the second render of a page nearly free, and it is why a viewer can pan and zoom without re-decoding.

Until 0.33 nothing bounded it. The eviction API (crate::DjVuDocument::enforce_cache_budget and friends) needed &mut DjVuDocument, and every render entry point holds a shared &DjVuPage — so a program that only rendered could never shrink what it grew. A sweep through a colour book cost about 5.3 MB per page and never gave any of it back.

This module closes that: every page cache registers itself here, every cache fill reports its new size, and when the total goes over [budget] the least-recently-used layers are dropped until it is under again. The default ceiling is [DEFAULT_BUDGET]; set your own with [set_budget], or lift it entirely with set_budget(usize::MAX).

The unit of eviction is a layer, not a page (#813): each decoded background, mask, converted pixmap and tile store carries its own last-used tick and size, and a sweep ranks them across every live page. A page whose mask was just used keeps its mask while its stale background goes. Only the layer being filled at that moment is protected, so the resident total can exceed the ceiling by at most one layer. (Until this change the sweep dropped whole pages and protected the whole page being rendered, so the overshoot was a page’s cache and a warm layer went with its cold neighbours.)

Eviction is safe at any moment. A cached layer is handed to a render as a shared handle, so dropping the cache’s own handle mid-render only means the render finishes with the copy it already holds. A render in progress therefore holds the layers it has already fetched whether or not the cache still does; that memory is the render’s, not the cache’s, and is not part of the resident total.

The ceiling is process-wide on purpose: memory is a process-wide resource, and a page does not know which document it belongs to. Per-document control is still available through crate::DjVuDocument::enforce_cache_budget, which stays page-granular.

See PERF_EXPERIMENTS.md READ_CACHE_BOUNDED and RENDER_CACHE_LAYER_EVICT.

Constants§

DEFAULT_BUDGET
The ceiling applied when the program sets none: 256 MiB.

Functions§

budget
The ceiling on the total resident bytes of all page render caches.
clear
Drop every registered page cache, whatever the ceiling. Returns bytes freed.
enforce
Drop least-recently-used cached layers until the total is at most budget. Returns the bytes freed; 0 when already under the ceiling.
resident_bytes
Approximate resident bytes held by every page render cache in this process.
set_budget
Set the ceiling. Pass usize::MAX to render without one (the behaviour of 0.32 and earlier).