#cache #lru-cache #disk #object #byte #vfs #assets

asset_lru

A two-level cache for objects which are bigger in memory than on disk

6 releases

0.1.3 Dec 12, 2021
0.1.2 Nov 7, 2021
0.0.3 Oct 24, 2021

#337 in Caching


Used in synthizer

BSL-1.0 license

37KB
646 lines

asset_lru

Actions

docs

Sometimes you want to cache assets from disk or somewhere else expensive. Sometimes those assets are much smaller as compressed/encoded bytes. This crate provides a reasonably smart strategy for such cases, where the encoded bytes are cached in memory as well as the decoded object.

This is very new, but with good code coverage via unit tests.


lib.rs:

A set of LRU caching mechanisms intended for smallish numbers of large objects.

Sometimes, you have something like a compressed JSON file on disk, or maybe a lossy audio file, which is 10 times smaller or more than the decoded representation after decompression/decoding. Reading this from disk and running the decoding process over and over is costly, but at the same time a simple map of keys to cached values will just grow forever and isn't very smart because it can't optimize the case where we have enough memory to keep the bytes from disk around as well. This crate provides a solution to that problem via two types and some traits:

[CostBasedLru] is a standard Lru cache which supports giving each item a cost. When the cost is exceeded, the cache will evict until the cost is below a threshold. This is the basic low-level building block, and is exposed because it's useful in other contexts. This is the simplest piece to use: you just throw items at it.

The higher level piece is [AssetCache], which returns Arcs wrapping a decoded item read from a [Vfs], with a complex caching strategy:

  • First, we can cache the bytes we read from disk in an [CostBasedLru] if the object from disk is below a configurable threshold, evicting from the backing LRU as necessary.
  • Next, we can cache the decoded object if the object's size is under a configurable threshold, in the same way.
  • After that, if we don't cache the object at all, we can keep it around as a weak reference so that we can return the same one as long as something outside this crate is keeping it alive.
  • And finally, for really important items, you can call cache_always to entirely short-circuit the mechanism and keep them around forever outside the book-keeping mechanisms.

To use this crate, implement the [Vfs] and [Decoder] traits, then construct a [AssetCache] with your chosen [AssetCacheConfig]. For simpler usage with a filesystem directory, use [FilesystemVfs], which does this for you.

A blanket impl of [Vfs] is provided for std::sync::Arc so that any Arc to a Vfs is itself a Vfs. This allows for sharing a Vfs between caches or anything else that might need it.

Dependencies

~1.1–1.7MB
~35K SLoC