Skip to main content

Module script_cache

Module script_cache 

Source
Expand description

script_cache submodule. rkyv-backed bytecode cache for zsh scripts.

Single-file shard at ~/.zshrs/scripts.rkyv. On 2+ runs of a given script, lex/parse/compile is skipped — the cache hit is mmap + zero-copy ArchivedHashMap lookup + bincode-decode of the inner fusevm::Chunk blob.

Storage layout (rkyv archived): ScriptShard { header: { magic, format_version, zshrs_version, pointer_width, built_at_secs }, entries: HashMap<canonical_path, ScriptEntry>, } ScriptEntry { mtime_secs, mtime_nsecs, binary_mtime_at_cache, cached_at_secs, chunk_blob: Vec<u8> }

Inner chunk_blob is bincode for now — fusevm::Chunk is owned by the upstream fusevm crate and only derives serde::Serialize/Deserialize, not rkyv::Archive, so the inner codec stays bincode inside the rkyv outer container. Direct rkyv on Chunk would require either forking fusevm or a mirror archived type — both are large refactors and not needed for the current “kill SQLite for bytecode” goal.

Read path:

  • Lazy mmap of the shard, kept alive for the process lifetime so repeat lookups pay validation once.
  • rkyv::check_archived_root::<ScriptShard> validates the byte image.
  • Header validated for magic / format_version / zshrs_version / pointer_width.
  • Per-entry: source mtime must match, and binary_mtime_at_cache ≥ running zshrs binary’s mtime (any rebuild of zshrs invalidates entries silently).

Write path:

  • bin_zsystem_flock(LOCK_EX) on scripts.rkyv.lock so concurrent writers serialize.
  • Read existing shard into owned form, mutate, rkyv::to_bytes, write to scripts.rkyv.tmp.<pid>.<nanos>, fsync, atomic-rename.
  • Drop the in-process mmap so the next read picks up the new shard.

Ported from strykelang/strykelang/script_cache.rs (the user’s stryke language has the same caching pattern; this is the same shape with ZRSC magic, zshrs version pin, and a single chunk_blob per entry — zshrs has no separate AST cache).

Structs§

ArchivedScriptEntry
An archived ScriptEntry
ArchivedScriptShard
An archived ScriptShard
ArchivedShardHeader
An archived ShardHeader
MmappedShard
mmap + validated *const ArchivedScriptShard. Self-referential — the pointer is valid for the lifetime of the wrapping struct.
ScriptCache
Shard cache keyed by canonical script path. One per shard file.
ScriptEntry
ScriptEntry — see fields for layout.
ScriptEntryResolver
The resolver for an archived ScriptEntry
ScriptShard
ScriptShard — see fields for layout.
ScriptShardResolver
The resolver for an archived ScriptShard
ShardHeader
ShardHeader — see fields for layout.
ShardHeaderResolver
The resolver for an archived ShardHeader

Constants§

SHARD_FORMAT_VERSION
Bumped on incompatible rkyv schema changes.
SHARD_MAGIC
Magic header bytes — fail-fast if a wrong-format file is mmap’d. “ZRSC” little-endian.

Statics§

CACHE
Process-wide ScriptCache rooted at default_cache_path(). None when the cache is disabled or the path could not be opened.
CACHE_DISABLED
Process-local disable flag set by parity-mode flags (--zsh etc.) in bins/zshrs.rs. Preferred over ZSHRS_CACHE=0 in env so the env var doesn’t leak into ${(k)parameters} and inflate the param count vs reference zsh.

Functions§

cache_enabled
ZSHRS_CACHE=0|false|no (env) or CACHE_DISABLED=true (process- local) disables the cache entirely.
clear
clear — see implementation.
default_cache_path
Default shard path: ~/.zshrs/scripts.rkyv.
evict_stale
evict_stale — see implementation.
file_mtime
file_mtime — see implementation.
stats
stats — see implementation.
try_load_bytes
Try to load cached chunk-bytes by source path. Returns None on any miss.
try_save_bytes
Store bincode-encoded fusevm::Chunk bytes for a script path. Best-effort — cache disabled / canonicalize failure / mtime stat failure all return Ok(()) silently so the caller can fire-and-forget.