Skip to content

serve: --prompt-cache-file <path>, the long prompt prefix saved to disk and restored across restarts (opt-in) - #2077

Closed
imanu86 wants to merge 1 commit into
Niko1221:mainfrom
imanu86:pr/prefix-disk
Closed

imanu86 wants to merge 1 commit into
Niko1221:mainfrom
imanu86:pr/prefix-disk

Conversation

@imanu86

@imanu86 imanu86 commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Title

Issue: none (an opt-in feature: the prompt prefix survives a restart).

Summary

--prompt-cache-file <path> (opt-in) writes the root checkpoint of the shared prompt prefix to a file and reads it
back at the next start, so the first turn after a restart resumes from the saved prefix instead of reading it again.
Format v2 holds one image per --layer-split block (so it works with two cards) and the MTP drafter's root cells.
Without the option nothing changes.

Why

The in-RAM prompt cache (--prompt-cache-tail / --prompt-cache-every) dies with the engine. An agent session
(Claude Code through a local gateway here) starts with a 40-130K prefix that is the same across restarts; every
restart of the server re-read it. Measured on this box the first 40K prompt after a restart went from ~42 s to
16-20 s with the file.

What changed

  • src/core/prefix_cache_file.cpp, include/strata/core/prefix_cache_file.hpp (new, library strata_prefix_cache):
    the file format (header with the engine's identity, one image per block, the drafter's root), write and read,
    BCrypt SHA-256 on Windows / the C++ fallback elsewhere.
  • src/program/generate.cpp: the option; the save after the root checkpoint is taken, the restore at start-up
    before the first request; host memory checked with available_host_bytes() before the restore; the file's
    identity covers the executable, the arguments and the STRATA_* / CUDA_* environment, so a file written by
    another configuration is replaced, never misread.
  • src/core/mtp.cpp, include/strata/core/mtp.hpp: the drafter uses first_needed() so every cell of the saved root
    is computed, not only the ones the current window asks for.
  • src/core/prefix_cache_file_test.cpp: the format, round trip and identity checks.
  • CMakeLists.txt: the library and the test.

Relation to open work

#1937 (parked conversations on the disk, --conversation-disk-dir) and #1810 (conversation checkpoints with disk
restore) persist conversations of the conversation cache; this persists the shared prompt prefix root (the
--prompt-cache checkpoint every conversation of a session starts from, including the drafter's state) and is
independent of the conversation cache. They can coexist; none of them is merged at the time of writing.

Measurements

RTX 2080 Ti 22 GB + RTX 3060 12 GB, Windows 11, --layer-split 16 --pipeline-windows 2, Qwen3.8-Flash-Next IQ3_XXS.
Reading a 40K-token first prompt takes ~42 s on this box; with the file the first turn after a restart resumes from
the saved root instead (one image per block read from an NVMe). Decode and later turns are unchanged; the output tokens
are the same with and without the file (the same checkpoint, read from RAM or from the file). The save/restore path has
run in this fork's daily build since 0.1.40 with 40-130K prefixes. On v0.1.43 the branch was built and started twice
with the option (prefix disk cache: enabled, identity computed in 17-23 ms), same answers.

Risks / limits

Opt-in. The file is rewritten when the identity changes (a new engine build, a changed option): one re-read, as
without the option. A file of a different format version is ignored and replaced.

Part of a series from a public patch registry (stack/ in the fork imanu86/Strata-2080Ti).

…sk and restored across restarts (opt-in)

The in-RAM prompt cache (--prompt-cache-tail / --prompt-cache-every) dies with the engine: an agent session that
restarts the server reads its 40-130K prefix again. With --prompt-cache-file the root checkpoint of the shared prefix
is written to that file (format v2: one image per --layer-split block, the MTP drafter's root cells included,
first_needed() so every drafter cell of the saved root is computed) and read back at the next start, so the first
turn after a restart resumes from the saved prefix. The file's identity covers the executable, the arguments and the
STRATA_*/CUDA_* environment: a file from another configuration is replaced, never misread. Host memory is checked
with available_host_bytes() before the restore. Off by default; without the option nothing changes.

prefix_cache_file_test covers the format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
imanu86 added a commit to imanu86/Strata-2080Ti that referenced this pull request Oct 12, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
later-3 added a commit to later-3/Strata that referenced this pull request Oct 13, 2026
@qiuzan2001

Copy link
Copy Markdown

Found by reading (no Mac here to build): src/program/generate.cpp is also compiled by the Mac engine, and the new identity block uses device_properties.uuid.bytes / stage_properties.uuid.bytes in the non-HIP branch (lines 7775 and 7796 on this branch). Metal's strata::gpu::DeviceProp (metal/include/strata/gpu/runtime.hpp) has no uuid field, and prefix_cache_file.cpp is not in metal/CMakeLists.txt's host sources, so the Metal build would stop there; a STRATA_GPU_METAL guard (or a per-backend helper for the identity) would keep it building. Also, the new tests are registered only under STRATA_BUILD_CONVERSATION_TESTS (off by default), and the option has no DETAILS.md entry yet; the header cites docs/sm75/BENCHMARKS.md, which is not in the repo.

@Niko1221

Copy link
Copy Markdown
Owner

Thank you. See #1090: one disk design will be picked; not measured here.

@Niko1221

Copy link
Copy Markdown
Owner

Thanks for the pull request.

We're resetting the tracker for 0.2.0-beta. There are more than 1,300 open issues and pull requests, too many for us to review properly, so we're closing everything that isn't being worked on right now. Closed here does not mean rejected.

To reopen it takes about two minutes:

  1. Rebase on main if it no longer applies, and re-run your checks on 0.2.0-beta.
  2. Start the title with its area: [Engine], [GUI], [TUI], [Benchmark], [Docs] or [Other].
  3. Fill in the pull request template: the problem and result, and the validation (what you ran, on which revision, what you saw).
  4. Comment /reopen. A check runs and either reopens the pull request or lists what is still missing.

The rules are in CONTRIBUTING.md.

@Niko1221 Niko1221 closed this Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants