Skip to main content

Module script_cache

Module script_cache 

Source
Expand description

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
ScriptEntryResolver
The resolver for an archived ScriptEntry
ScriptShard
ScriptShardResolver
The resolver for an archived ScriptShard
ShardHeader
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.

Functions§

cache_enabled
ZSHRS_CACHE=0|false|no disables the cache entirely.
clear
default_cache_path
Default shard path: ~/.zshrs/scripts.rkyv.
evict_stale
file_mtime
stats
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.