wasm_code_cache (wasm v0.1.0)
View SourceCompiled code, kept on disk so a node restart does not pay for it again.
Compiling QuickJS is about twenty seconds of a core. Nothing waits for it, so it is not a latency problem, but it is twenty seconds every time a node starts and every time an instance of a module it has never seen goes hot. This makes it once.
Off unless you turn it on. Reading a .beam from disk and loading it is
executing whatever is in that file, so the directory holding the cache is as
trusted as the code in your release. Wasmtime's cache is opt-in for the same
reason. Set it in the application environment:
application:set_env(wasm, code_cache_dir, "/var/cache/my_app/wasm").What a key covers
Everything that would make an artifact wrong if it changed, which is more than the module:
- the module's content hash, so two different modules never collide
- the ABI between generated code and
wasm_exec - the OTP release and the emulator flavour, because generated BEAM is only loadable by the emulator that compiled it
- the machine's architecture
- the compiler quality asked for, since
baselineandfullare different code - the set of functions compiled, because the tier compiles what ran and two workloads reach different sets
- the slot the artifact was built for, because a module's name is part of its BEAM file and cannot be changed without rewriting it
A module identified by a reference() rather than a content hash is never
cached. That is every module built from text: its identity is fresh on every
validation, so there is nothing stable to key on.
What it does not do
No sharing between nodes, no signature, no compression. A cache entry is a file named for the hash of its key, and eviction is by total size, oldest first.
Summary
Functions
Where the cache lives, or undefined when it is off.
The key for one artifact, or undefined when this module cannot be cached.
The artifact for this key, if there is one and it is readable.
Throw the cache away. For tests, and for a release that wants a clean start.
Keep this artifact under this key.
Functions
-spec dir() -> undefined | file:filename().
Where the cache lives, or undefined when it is off.
-spec key(term(), non_neg_integer(), module(), baseline | full, [non_neg_integer()], term()) -> binary() | undefined.
The key for one artifact, or undefined when this module cannot be cached.
Identity is #module.identity: only the {sha256, _} form is stable enough
to key on, and a reference() answers undefined here rather than being
hashed, because a fresh reference every validation would fill the cache with
entries nothing can ever hit.
The artifact for this key, if there is one and it is readable.
Any failure is a miss. A cache that cannot be read is a slower start and never an error, which is the same rule the rest of the tier follows: every refusal means do the work.
-spec purge() -> ok.
Throw the cache away. For tests, and for a release that wants a clean start.
Keep this artifact under this key.
Written to a temporary name and renamed, because a half-written .beam that a
later start reads is a crash rather than a miss, and rename is atomic on every
filesystem this runs on.