Today we trade one good thing for another. Evict (keep the last 3 screenshots) keeps context short and quality high — but rewriting an old screenshot in place breaks the KV prefix every step, so the whole history is re-prefilled (~0% cache hit, 131 s prefill/step, quadratic on long tasks). No-evict (keep everything) makes the prefix stable so the cache is reused (~2× less prefill) — but context grows unbounded: decode slows, memory OOMs, and accuracy drops −6.4 pp. The theoretical optimum is both at once: keep evict's short context (full quality, fast decode, no OOM) and pretend every step is a cache hit, so only the new screenshot + text is prefilled. We do not build it to get its numbers — we simulate it by replaying the tasks we already ran: take no-evict's measured only-new prefill and pair it with evict's measured decode, quality, and bounded memory. That is a computed upper bound, not a projection.
The bound, in one line. On the matched clean subset (n=78) the theoretical optimum is evict's quality at no-evict's speed: same score (no −6.4 pp loss), 2.1× wall-clock, ~2× energy, bounded memory. It is a fiction (a real cache can't reuse the retained screenshots for free — their KV depends on the evicted one), so the closest physically buildable approach is terminal screenshot slots + a state checkpoint/restore (§ mechanism). The two halves of the bound are each already measured — the optimum just takes the better half of each.
| coefficient | evict (baseline) | no-evict | combinational optimum (computed) | measured optimum (genuine patch) | 2×A6000 (GPU ref) |
|---|---|---|---|---|---|
| Setup | |||||
| platform | NUC16 CPU 16C | NUC16 CPU | NUC16 CPU | NUC16 CPU | 2× RTX A6000 48GB ea |
| screenshot context | last 3 — bounded | all — grows | last 3 — bounded | last 3 — bounded | last 3 |
| KV prefix each step | broken (rewrite) | stable (append-only) | prior reused (assumed) | prior reused (cache_n=L) | re-prefilled (no reuse) |
| Prefill · per step | |||||
| prefill tokens / step (tok) | 5148 | 2353 | 2353 (only-new) | 2058 (only-new) | ~5.1K (re-prefill) |
| KV cache hit (%) | ~0 | 64 | ≈64 (= no-evict) | ≈63 (measured) | — |
| prefill throughput (tok/s) | 38.7 | 37.5 | 37.5 | 36.9 | ~1.1–2.9K (28–75×) |
| prefill / step (s) | 131.6 | 62.9 | 62.9 (2.09×) | 55.8 (2.36×) | ~1–2 (CUDA) |
| Decode · per step | |||||
| decode tokens / step (tok) | 301 | 268 | 301 (= evict) | 301 (= evict) | ~300 |
| decode throughput (tok/s) | 15.0 | 13.5 | 15.0 | 15.0 | ~150 (≈10×) |
| decode / step (s) | 19.5 | 23.0 (slows) | 19.5 (= evict) | 19.5 (= evict) | ~2 (≈10×) |
| Per agent-step | |||||
| step latency (s) | 151.2 | 85.9 | 82.4 (1.83×) | 75.3 (2.01×) | ~3.5 |
| agent-steps / hour | 23.8 | — | 43.7 (1.84×) | 47.8 (2.01×) | ~1000 (GPU) |
| Per task | |||||
| steps / task | 9.4 | 8.1 | 9.4 (= evict) | 9.4 (= evict) | — |
| task score | 0.858 | 0.782 (−6.4 pp) | 0.858 (= evict) | 0.858 (= evict)* | 0.804 † |
| wall / task (s) | 1819 | 784 | 857 (2.12×) | 786 (2.31×) | — ‡ |
| energy / task (Wh) | 18.3 | 10.0 | 9.5 (1.93×) | 8.7 (2.12×) | — ‡ |
| Footprint | |||||
| peak KV memory | bounded | OOM tail | bounded | bounded | bounded |
| nature | measured | measured | computed bound | measured — genuine run | external live run |
evict / no-evict / combinational optimum are the matched clean subset (n = 78, steps ≤ 20): evict and no-evict are measured on this NUC16 run; the combinational optimum is computed by splicing no-evict's only-new prefill onto evict's decode / quality / memory (theoretical_optimum.py). The measured optimum is the genuine fake-prefix patch (n_fake_cached, vision-inclusive) replayed over all 141 baseline tasks and aggregated on the same n=78 subset for an apples-to-apples comparison — it prefills the true ~2058 only-new tokens, so it even edges the computed bound (55.8 s vs 62.9 s/step) and reaches no-evict's wall (786 s ≈ 784 s) while keeping evict's score and bounded memory. Over the unrestricted full-141 distribution (incl. the deep-context long tail) the gain is larger still: prefill 3.43×, wall 2.66×, energy 2.68×. Traffic-light coloring (worst red, best green, ties white) applies to the four NUC16 columns only. † A6000 score is the official OSWorld leaderboard mean over 361 tasks (different set); its ~28–75× prefill / ~10× decode ratios and ~1–2 s/step prefill are from the live 2×A6000 run; ‡ per-task wall/energy absolutes are pending that live feed (—). The A6000 column is rendered green as the datacenter-GPU reference (it is not a NUC16 KV regime; the traffic-light comparison is among the four NUC16 columns). *score / decode are evict's by construction — the patch discards the (garbage) output token; it measures prefill timing, not quality.
Cross-reference: the architecture facts, the eviction/no-eviction mechanics, and the hybrid-model constraints referenced below are established in the sibling page Holo3 on OSWorld — Acceleration. Read it first if you have not.
The goal is a Holo3-35B-A3B GUI agent on OSWorld-Verified, served on a single Intel NUC (96 GB) via llama.cpp CPU, that runs at eviction-level quality with no eviction-level cost. We have two real arms today, and each pays for what the other gets for free:
The theoretical optimum is: "evict, with the re-prefill cost magically removed." Concretely — keep evict's bounded 3-screenshot context (so quality, decode rate, memory, trajectory, and score are byte-identical to evict), but pretend every step is a perfect cache hit so that only the genuinely new content (the one new screenshot + the text delta) is ever prefilled (so prefill equals no-evict's only-new cost).
It is essential to be clear: this is not a system we built and not a run we executed. It is a number COMPUTED from the two arms we already measured (theoretical_optimum.py over the live no-evict run). It is the tightest upper bound a perfect KV cache could reach on a bounded screenshot window, and nothing more.
The optimum is an honest cross-arm splice. Each column is sourced from exactly one measured arm, with a stated justification — it is not a cherry-pick of each arm's best cell.
Prefill ← no-evict (62.9 s, 2353 tok/step). No-evict physically measured the cost of prefilling only the new content per step: its byte-stable prefix is a genuine cache hit, so its reported per-step prompt_tokens (~2353) are the non-cached tokens actually processed, not the full context. (This is verified: no-evict's cached_tokens grow 0 → 44K while the new prompt_tokens it must prefill stays flat at ~2160–2225 regardless of context depth. If 2353 were the total context it would exceed evict's 5143 on multi-step tasks — it is smaller, proving it is post-cache.) In a bounded 3-window served by a perfect cache, the genuinely-new content per step is the same quantity — add one screenshot and a text delta, drop the oldest screenshot — so no-evict's measured only-new prefill is the optimum's prefill. This is why the prefill-equivalence is real, not assumed.
Decode, score, steps, memory ← evict (19.5 s decode, 0.858, 9.4 steps, bounded). The optimum keeps evict's bounded context and feeds the model byte-identical inputs — the only thing the fiction changes is prefill timing, never the KV contents decode sees. Therefore:
Why decode is legitimately evict's, and why it must NOT be no-evict's. Decode rate is governed by total KV residency (context length), not by how the KV got there. A cache hit and a fresh recompute produce numerically identical KV tensors at identical positions; decode-time attention is a fixed memory-bandwidth sweep over those tensors, so there is no mechanism by which provenance changes per-token cost. Empirically, no-evict's per-step decode falls monotonically 17.5 → 4.0 t/s as reconstructed context grows 5K → 44K (n=631 step-profiles) — purely a context-size effect. Cross-check: evict's measured mean decode is 14.96 t/s and no-evict's decode in the matched 5–10K-token bucket is 14.9 t/s — equal context ⇒ equal decode across arms, to within noise. The optimum holds evict's bounded context, so it inherits evict's ~15 t/s by construction. (Note the hybrid architecture is why decode is still context-dependent at all: the 30 Gated-DeltaNet layers are O(1) per token regardless of arm, but the 10 attention layers impose a ctx-linear term — a linear fit gives decode_time/token ≈ 31.3 ms + 4.6e-6 s × ctx. The O(1) recurrent majority does not make decode context-free.) Predicted-token counts are comparable across arms (~268 no-evict vs ~291 evict), so evict's faster decode is a genuine small-KV effect, not an artifact of generating fewer tokens.
Wall ← computed by swapping only the prefill component.
opt_wall = evict_wall − (evict_prefill − optimum_prefill) × steps
= 1818.9 − (131.5 − 62.9) × 9.4
≈ 858.1 s
Only the prefill component is replaced; VM/action time and decode are held fixed at evict's values. This is safe because model time is 94.9 % of wall and non-model time is only 5.1 % — a small, prefill-independent constant (verified: 0/78 negative residuals). The wall identity swaps only prefill; the implied VM/overhead residual (~5 % of wall) is nonnegative on all 78 tasks and held fixed, so there is no hidden second saving.
Energy ≈ wall (9.4 Wh). Energy is scaled by the wall ratio under near-constant package power (47.2 W ± 9.5 W). Because the removed seconds are compute-bound prefill (above-average power), constant-power scaling under-credits the saving — so 9.4 Wh is, if anything, slightly conservative (a hair too high), which is the safe direction for an upper bound. The per-task energy ratio equals the per-task wall ratio by construction; the aggregate gap (energy 1.93× vs wall 2.12×) is a mean-of-ratios-vs-ratio-of-means weighting artifact, not an independent energy effect.
Why the optimum's wall (858 s) can EXCEED no-evict's (784 s) yet still dominate it. The optimum keeps evict's 9.4-step trajectory at full quality, while no-evict reaches the finish in only 8.1 steps — but at −6.4 pp accuracy and with an unbounded-memory OOM tail. The optimum does not double-dip on no-evict's cheaper, lower-quality trajectory. Per step, the optimum (82.4 s) actually beats no-evict (85.9 s): it pairs no-evict's cheap prefill with evict's non-degrading decode (19.5 s vs no-evict's 23.0 s). So within the optimum's contract — byte-identical outputs to evict, bounded window, VM fixed — it is the same speed class as no-evict with none of the accuracy loss or memory blowup.
What the fiction assumes away. On this hybrid model the 2 retained screenshots' attention KV depends on the evicted screenshot (cross-attention), and their absolute positions shift when the oldest is dropped — so a real bounded cache cannot reuse them for free. The 30 Gated-DeltaNet recurrent layers carry an O(1) running state that cannot be mid-window spliced at all. The bound assumes every step is a free cache hit anyway. This is exactly what makes 858 s an upper bound (unreachable while bounded) and not a buildable number.
Matched clean subset, n = 78, COMPUTED upper bound. The subset excludes 8 runaway tasks (> 20 steps / > ~60K-token context — the memory-blowup tail); all three arms are over the same tasks. evict and no-evict are measured; the theoretical optimum is computed from those two arms (it is not a run).
| coefficient | evict (measured) | no-evict (measured) | theoretical optimum (computed) |
|---|---|---|---|
| score | 0.858 | 0.78 (−6.4 pp) | 0.858 — = evict, copied by construction |
| prefill / step (s) | 131.5 | 62.9 | 62.9 — = no-evict (only-new) |
| decode / step (s) | 19.5 | 23.0 (degrades w/ ctx) | 19.5 — = evict (bounded KV), copied |
| step latency (s) | 151.0 | 86.0 | 82.4 — 1.83× vs evict |
| new tokens / step | 5143 | 2353 (non-cached) | 2353 — = no-evict |
| KV cache hit | ~0 % | 64 % (measured prefix) | 100 % — assumed (fiction) |
| wall / task (s) | 1818.9 | 784 | 858.1 — 2.12× vs evict |
| energy / task (Wh) | 18.3 | 10.0 | 9.4 — 1.93× vs evict (conservative) |
| agent-steps / hour | 23.8 | — | 43.7 — 1.84× vs evict |
| steps / task | 9.4 | 8.1 | 9.4 — = evict trajectory (NOT no-evict's 8.1) |
| memory | bounded | grows → OOM tail | bounded — = evict |
Notes that belong with the table:
Why exact is impossible on this hybrid model. Of Holo3's 40 layers, only 10 are full-attention (position-indexed KV); 30 are Gated-DeltaNet recurrent layers carrying an O(1) running state, not per-token KV (see the sibling page). Splicing a token out of the middle of the sequence — which is what a bounded sliding window requires — is inert and unsound on the recurrent half: seq_rm + seq_add + K-shift / --cache-reuse would corrupt 30/40 layers. So the pure bound (prefill only the ~1 new screenshot, ~2.4K tok) cannot be realized exactly while the window is bounded. The bound is the target; it is not the build.
No-evict is the arm that realizes the prefill bound (2353 tok/step, only-new) — but only by leaving context unbounded, which is what costs it decode degradation, the OOM tail, and −6.4 pp. It is the measured proof that only-new prefill is achievable; it is not a stable system.
The closest physically-realizable approach — terminal-slot + state checkpoint/restore. This is exact for all 40 layers and bounded, at the price of re-prefilling the current ≤3-image window (~6K tok/step) instead of the bound's ~1 image (~2.4K). Lay the prompt as:
[preamble] [append-only text history] [ ≤3 screenshots at the END ]
Checkpoint the full state (attention KV + recurrent state) at the start of the image region. llama.cpp already ships the primitives: --ctx-checkpoints, and llama_state_seq_get_data_ext / llama_state_seq_set_data_ext with LLAMA_STATE_SEQ_FLAGS_PARTIAL_ONLY.
Per-step algorithm:
Because the checkpoint sits before the image region, this pays more than the bound (3 images/step ≈ 6K tok vs the bound's ~1 image ≈ 2.4K) — but it is exact, bounded, and constant-cost. On long tasks it crushes evict outright (constant ~6K vs evict's growing 5K → 27K), so 858 s should be read as the target, with terminal-slot as the realizable system that approaches it from above.
We replay each task's measured evict trace and, at every step, swap only the prefill cost (full re-prefill → only-new content). Decode and VM action are evict's, untouched. One real success (chrome/bb5e4c0d, 7 steps) decomposed per step into prefill, decode, action:
Evict (top) hits the step-4 cliff — the 3-screenshot eviction rewrites an early token, the KV prefix collapses to the 947-token preamble, and prefill triples (≈60 s → ≈175 s) and never recovers. The optimum (bottom) keeps prefill flat (~55 s) because only the new screenshot is charged: the task contracts 1.9× (1031 s → 546 s) with the cliff gone. Across the matched subset (n=78) the simulator gives wall 1819 s → 834 s (2.18×) and energy 18.3 → 9.3 Wh (1.96×), matching the aggregate bound within the per-step-rate slack.
Everything above is the computed bound. We then built the actual engine change — an
n_fake_cached patch to llama.cpp (coding guide ↗) that, per
request, fabricates a depth-L prior KV (valid positions, never computed) and prefills only-new — and
replayed a complete real OSWorld task through it, vision-inclusive: every step sends the real recorded
screenshot (genuinely vision-encoded) against the fabricated depth-L window. This measures the
optimum on the production server instead of inferring it.
chrome/3720f614 (8 steps, score 1.0): task prefill 1050 s → 448 s measured (2.35×) vs
442 s predicted (2.38×) from the combined curve; wall 1236 s → 633 s (1.95×) — inside the aggregate
bound's band (prefill ≈2.05×, wall ≈1.9–2.2×).| step | full depth (tok) | evict baseline (s) | computed bound (s) | genuine run (s) | bound ÷ run |
|---|---|---|---|---|---|
| 1 | 3025 | 64.0 | 52.3 | 53.5 | 0.98 |
| 2 | 5214 | 57.9 | 53.9 | 54.9 | 0.98 |
| 3 | 7431 | 59.5 | 55.6 | 56.3 | 0.99 |
| 4 | 7611 | 169.8 | 55.7 | 56.6 | 0.99 |
| 5 | 7821 | 171.1 | 55.8 | 56.3 | 0.99 |
| 6 | 8065 | 173.5 | 56.0 | 56.6 | 0.99 |
| 7 | 8303 | 176.3 | 56.1 | 56.9 | 0.99 |
| 8 | 8487 | 178.3 | 56.2 | 56.9 | 0.99 |
| task | — | 1050 | 442 | 448 | 0.99 |
Both the computed and the run columns are vision-inclusive (the new screenshot is encoded every step).
The genuine run holds prefill flat at ~56 s while the evict baseline jumps 60 → 170 s at step 4
(the KV-collapse cliff) — the same cliff the simulation predicts, now measured.
Every step's fabricated hit registered exactly (cache_n == L); the underlying mechanism was separately
cross-validated against an independent cb_eval profiler to ±3% over a 0–40k-token depth sweep.
The computed bound (442 s) sits just below the real run (448 s) because the per-step rate model is mildly
optimistic — i.e. the bound is honest, not over-claimed.
Read first: this section assumes the architecture facts and the three-arm A/B numbers established on the sibling page,
/demos/holo3-osworld-acceleration.html— the 10-attention / 30-Gated-DeltaNet hybrid split, why--cache-reuseis inert and unsound here, and the evict / no-evict / theoretical-optimum table. All numbers below are the matched clean subset, n = 78 (exclude rule: > 20 steps ≈ > 60 K-token context = the 8-task memory-blowup tail), recomputed live bytheoretical_optimum.pyover the current no-evict run.The asterisk on everything in Clusters A–D: almost every result below was developed on standard transformers with per-token KV on all layers. On those models the "relocate / evict a KV segment in the middle and re-rotate positions" family is sound. On Holo3 it is sound only for the 10 attention layers — the 30 recurrent layers have no per-token KV to splice, so the exact analogue of any "KV segment" trick is a state checkpoint, not a KV edit.
For each cluster: the most useful works, the concrete building block, and scope — does it apply to the bound (the computed 858 s / 9.4 Wh upper bound), to the buildable terminal-slot approach (the realizable ~6 k-tok/step approximation), or only to the 10 attention layers?
This is the conceptual ancestor of "a screenshot is a reusable slot."
[p0,p1) range tracked from the mtmd injection. Its limit here is architectural — Prompt Cache assumes the segment is per-token KV re-slottable by re-assigning positions; on our 30 recurrent layers there is no per-token KV to re-slot. The faithful realization of a "reusable screenshot slot" is therefore a state checkpoint of the prefix that ends where the screenshots begin — not a relocatable KV chunk. This is exactly why our slots must be terminal. → informs the buildable terminal-slot layout.Verdict (A): the slot abstraction is right; the implementation (relocatable KV chunk + RoPE re-rotation) is sound only for the 10 attention layers. The 30 recurrent layers force the exact analogue to be a state checkpoint, which is what makes terminal-slot checkpoint-restore — not a KV-pointer swap — correct.
Legitimizes "renumber surviving positions inside the cache" — the path the sibling page ruled out here.
seq_rm+seq_add+K-shift triad we cannot use on the recurrent half.Verdict (B): every primitive edits per-token KV positions → 10 attention layers only, and on Holo3 the full triad silently corrupts the 30 recurrent ones. What this cluster does give the buildable scheme are two disciplines: (1) pin the sink — keep the preamble prefix stable (it is the checkpoint root); (2) distance-limit — because the ≤K screenshots sit at the end and text history is append-only, retained positions never leave the trained range, which is why the terminal layout is benign.
Mostly dissolved by terminal slots — with the ≤3 most-recent screenshots always re-prefilled at the end, we never choose which old screenshot KV to drop.
Verdict (C): these choose what to drop; terminal-slot needs no victim selection. They become relevant only for K > 3 (GUI-KV/STaR-KV redundancy scoring to thin extra screenshots) or to push the bound on the attention layers only (VL-Cache budgets, Quest page-gating) — both safe to layer on top of checkpoint-restore, neither replaces it. → mostly bound rationale + optional attention-layer add-ons.
The production substrate that would hit the same hybrid constraint.
Verdict (D): all treat KV as a first-class object — the worldview in which "checkpoint this prefix, restore it next step" is a scheduling decision. But the same hybrid constraint applies: every one is prefix/block/text oriented; none models M-RoPE image positions or a Gated-DeltaNet recurrent state, and vLLM/SGLang currently lack mtmd + Gated-DeltaNet checkpoint serialization — which llama.cpp already ships via llama_state_seq_get/set_data_ext(LLAMA_STATE_SEQ_FLAGS_PARTIAL_ONLY). → infra for the buildable path, but only llama.cpp is recurrent-state-ready today.
The model-spec and risk cluster.
Verdict (E): the headline gift is negative and clarifying — the M-RoPE-shift correctness risk that dominates Clusters A/B is designed out by the terminal-slot layout, because we never move an image token's position; we restore an exact prefix and re-encode the screenshots fresh.
| # | path | what to build | prior work borrowed | effort | risk | expected payoff vs the n=78 numbers |
|---|---|---|---|---|---|---|
| (a) | Terminal-slot + --ctx-checkpoints — buildable now, exact, ~6 k tok/step. The closest realizable approach to the bound. |
Agent/server orchestration only, no model change. Lay the prompt as [preamble][append-only TEXT history][≤K screenshots at END]; checkpoint the full state (10 attn KV + 30 recurrent) at the image-region start; each step restore → prefill only the ≤K-image window (~6 k tok, constant) → decode → fold the new action text into the checkpoint. Uses --ctx-checkpoints + llama_state_seq_get/set_data_ext(PARTIAL_ONLY) — already shipping in llama.cpp. |
Prompt Cache (MLSys 2024) terminal-slot discipline; ChunkAttention (ACL Findings 2024) two-phase kernel shape; CachedAttention/AttentionStore (USENIX ATC 2024) checkpoint-restore primitive; StreamingLLM (ICLR 2024) pin-the-sink discipline. | M | Layout drift — reordering screenshots to the tail vs the interleaved leaderboard layout could move accuracy (the one open empirical, not numerical, question). | Exact for all 40 layers, bounded memory, evict's full score (no −6.4 pp). Pays ~6 k tok/step (re-prefills 3 images) vs the bound's ~2.4 k (≈1 image), so it lands between no-evict and the 858 s bound on per-step cost — and on long tasks it crushes evict (constant ~6 k vs evict's growing 5 k→27 k). The realizable target. |
| (b) | No-evict (append-only) — already measured; the run that produced these numbers. | Nothing to build — flip eviction off so the byte-stable prefix is a real cache hit. | (the measured proof that only-new prefill is achievable — 2353 non-cached tok/step at ~64 % hit) | S | Unbounded context → decode degrades (17.5 → 4.0 t/s as KV grows 5 K→44 K), OOM tail, −6.4 pp accuracy. | Realizes the prefill bound (62.9 s, 2353 tok/step) — but only by leaving context unbounded. Wall 784 s on subset, but the −6.4 pp loss and OOM tail make it a measurement proof, not a deployable target. The bound borrows its prefill, never its trajectory or decode. |
| (c) | Selective-recompute (CacheBlend / EPIC) — attempt an approximate bounded middle-splice closer to the ~2.4 k bound. | A correction pass that recomputes only high-deviation / chunk-boundary tokens of a relocated screenshot on the 10 attention layers, plus a recurrent-state reconstruction strategy (the hard, open part). | CacheBlend (EuroSys 2025) ~15 % high-deviation recompute; EPIC/LegoLink (ICML 2025) ≤32 boundary-token recompute; VLCache (2025) pre-RoPE image-KV relocation on Qwen3-VL-30B-A3B. | L | High — sound only on the 10 attention layers; the 30 Gated-DeltaNet layers have no defined splice, so any mid-window edit is approximate at best and needs a recurrent-state correction with no published recipe. | Could push toward the ~2.4 k bound (≈1 image/step) if the recurrent half can be approximately corrected — but this trades exactness for prefill, reintroducing a quality-A/B risk the terminal-slot path avoids. Research path, not a near-term build. |
| (d) | Paged / prefix serving (vLLM / SGLang) — same hybrid constraint. | Port the workload onto a paged/radix-tree server with mtmd + Gated-DeltaNet checkpoint serialization. | PagedAttention/vLLM (SOSP 2023) block tables; RadixAttention/SGLang (NeurIPS 2024) prefix index; LMCache (2025) truncation-collapse evidence; Mooncake (USENIX FAST 2025) tiered KV pool. | L | Blocked today — neither stack serializes a Gated-DeltaNet recurrent state or models M-RoPE image positions; they hit the identical hybrid-recurrent constraint and would need the same checkpoint primitive llama.cpp already has. | No payoff over (a) until upstream adds recurrent-state checkpoints. Same bound, more engineering. Track for production scale-out, not for first results. |
Instrument, per step, on all arms (extend theoretical_optimum.py's step-profile logging):
- per-step prefill tokens (split: cached-hit vs newly-processed — the post-cache "genuinely new" quantity),
- KV cache-hit ratio (and label fictions vs measurements: optimum = assumed 100 %, no-evict = measured ~64 %, evict = 0 %),
- decode t/s (the load-bearing variable — verify it tracks total KV residency, not provenance),
- score (per-task, OSWorld-Verified),
- peak KV memory.
A/B design — same n=78 clean subset, same tasks, exclude > 20 steps:
| arm | role |
|---|---|
| evict (today) | measured baseline (0.858, 131.5 s prefill, 1818.9 s wall, 18.3 Wh) |
| no-evict | measured (realizes only-new prefill; −6.4 pp, unbounded) |
| theoretical optimum | computed, not run — the 858.1 s / 9.4 Wh bound from theoretical_optimum.py |
| terminal-slot build (path 2a) | the new system under test |
Success criteria for the terminal-slot build: 1. Match evict's score (no −6.4 pp) — token-for-token output parity is the goal; first run the exactness sanity check (assert restore-then-prefill yields identical logits to a from-scratch full prefill on a fixed prompt — numerical proof the checkpoint is exact on this hybrid model). 2. Hold per-step prefill ≈ constant while bounded (~6 k tok/step regardless of task length), so wall/energy approach the 858 s / 9.4 Wh bound as task length grows (the gain is length-dependent: ~1.21× on ≤3-step tasks rising to ~2.61× on 11–20-step tasks). 3. Bounded peak KV memory (no growth, no OOM tail).
Failure signal: terminal-layout accuracy drift — if clustering screenshots at the tail and keeping older observations only as text moves agent behavior, score drops below evict. The fix is a layout tweak (what text survives, guided by GUI-KV/STaR-KV redundancy and FastV's "visual info migrates to text in early layers", ECCV 2024), not a correctness fix — the mechanism stays exact.
The theoretical optimum is a COMPUTED bound, not a system we run: it splices prefill from no-evict (the genuinely-new 2353 tok/step, trajectory-independent) onto score / steps / decode / memory from evict (copied by construction under the no-input-change argument — it keeps evict's 9.4-step trajectory, not no-evict's cheaper 8.1, so it does not cherry-pick), yielding 2.12× wall (1818.9 → 858.1 s), 1.93× energy (18.3 → 9.4 Wh), and zero quality loss vs evict (0.858) while bounded — dominating no-evict because it pairs cheap prefill with evict's non-degrading decode (82.4 s/step vs no-evict's 85.9 s). It is a fiction because on this hybrid model the retained screenshots' attention KV depends on the evicted one and their positions shift, while the 30 Gated-DeltaNet layers carry an O(1) state that cannot be mid-window spliced — so a real bounded cache cannot reuse them for free. The buildable terminal-slot + checkpoint-restore scheme is the closest physically-realizable approach: exact for all 40 layers, bounded, full-quality, but paying ~6 k tok/step (3 images) rather than the bound's ~2.4 k (≈1 image) because the checkpoint sits before the image region — so it lands between no-evict and the bound on short tasks and crushes evict on long ones. The single highest-leverage first step is path 2(a): build terminal-slot + --ctx-checkpoints and run the exactness sanity check — it needs no model change, the llama.cpp primitives (--ctx-checkpoints, llama_state_seq_*_data_ext(PARTIAL_ONLY)) already ship, and a passing logit-parity assertion immediately converts the computed bound from an argument into a realizable, bounded, full-quality acceleration. See /demos/holo3-osworld-acceleration.html §2b for the mechanism's architectural derivation.
Building blocks drawn from the literature. Slot/segment caching (Prompt Cache, CacheBlend, EPIC) is sound for the 10 attention layers; the 30 recurrent layers are why the exact scheme here is a state checkpoint, not a KV segment.
| work | venue | building block it gives us |
|---|---|---|
| Prompt Cache: Modular Attention Reuse for Low-Latency Inference | MLSys 2024 | The 'screenshot = modular KV slot with an assigned position range' abstraction, plus the schema-driven discipline of tracking each segment's exact [p0,p1) span — precisely the span-tracking we need to feed llama_memory_seq_rm / seq_add for in-cache eviction. |
| Block-Attention for Efficient Prefilling | ICLR 2025 | A concrete, validated recipe for the K-shift math (de-rotate -> zero -> re-rotate to target position) and the empirical reassurance that re-positioning cached KV need not degrade quality — the central feasibility argument for in-cache screenshot eviction. |
| CacheBlend: Fast Large Language Model Serving for RAG with Cached Knowledge Fusion | EuroSys (Best Paper) 2025 | The selective-recompute-to-repair-relocation primitive: an HKVD-style metric + gradual layer filter to decide which retained (image) tokens to refresh after an in-cache eviction, turning 'relocation is approximate' into a tunable accuracy/latency knob. |
| EPIC: Efficient Position-Independent Caching for Serving Large Language Models | ICML 2025 | (1) The PIC framing/vocabulary to position our contribution; (2) a targeted, very-low-cost correction (recompute only the first <=32 tokens of each relocated chunk to kill the relocation-induced attention sink) that is cheaper than CacheBlend's broader selective recompute. |
| KVLink: Accelerating Large Language Models via Efficient KV Cache Reuse | NeurIPS 2025 | The 'position re-index + lightweight link/glue tokens' template — evidence that after we renumber and K-shift the retained screenshots, a handful of learned or recomputed bridging tokens can repair the cross-screenshot attention seam left by an evicted span. |
| ChunkAttention: Efficient Self-Attention with Prefix-Aware KV Cache and Two-Phase Partition | ACL (Findings) 2024 | The 'KV stored as relocatable fixed chunks behind a content index' engineering pattern and a kernel-locality argument for why operating on per-screenshot chunk spans (rather than the monolithic cache) is efficient. |
| VLCache: Computing 2% Vision Tokens and Reusing 98% for Vision-Language Inference | arXiv preprint (not yet peer-reviewed) 2025 | The most directly transplantable building block: (1) store image KV pre-RoPE + per-image hash key (a position-independent screenshot slot); (2) re-apply position at the destination; (3) recompute only ~2-5% of (early) image tokens to bound cumulative M-RoPE relocation error — a concrete, cheap correctness budget for our open risk. |
| Efficient Streaming Language Models with Attention Sinks | International Conference on Learning Representations (ICLR) 2024 | The sink-retention + in-cache position-renumbering pattern: when we evict an old screenshot span, keep the leading sink tokens, renumber surviving positions contiguously, and re-rotate the retained keys via RoPE — exactly the K-shift path. Justifies that the retained window stays numerically valid. |
| llama.cpp context-shift / cache_reuse (--cache-reuse, n_keep) and self-extend (--grp-attn-n/--grp-attn-w) | Open-source project (GitHub ggml-org/llama.cpp); not a peer-reviewed paper 2024 | The concrete building block: seq_rm + seq_add + K-shift triad as the eviction+renumber+re-rotate operation, plus n_keep as the sink anchor and the cache_reuse chunk-matching logic as a model for keeping the cache a hit after a mid-sequence drop. |
| LM-Infinite: Zero-Shot Extreme Length Generalization for Large Language Models | North American Chapter of the ACL (NAACL) — Outstanding Paper 2024 | A principled cap on relative positions after renumbering (the distance limit) so the M-RoPE K-shift keeps retained image/text tokens within the trained positional range, reducing the risk that shifting pushes positions into untrained territory. |
| LLM Maybe LongLM: Self-Extend LLM Context Window Without Tuning | International Conference on Machine Learning (ICML) — Spotlight 2024 | The floor-division grouped-position remapping recipe as a template for renumbering surviving positions after we drop an image span — and proof that an inference-only position rewrite needs only minor code changes, not retraining. |
| DuoAttention: Efficient Long-Context LLM Inference with Retrieval and Streaming Heads | International Conference on Learning Representations (ICLR) 2025 | A per-head streaming-vs-retrieval budget so eviction of old screenshot spans is applied only where it is safe, preserving accuracy while still bounding memory and keeping the retained cache a hit. |
| H2O: Heavy-Hitter Oracle for Efficient Generative Inference of Large Language Models | Conference on Neural Information Processing Systems (NeurIPS) 2023 | An accumulated-attention scoring policy to select the evicted span by importance rather than age, a knob to trade memory vs the -6.4pp quality drop. |
| VL-Cache: Sparsity and Modality-Aware KV Cache Compression for Vision-Language Model Inference Acceleration | International Conference on Learning Representations (ICLR) 2025 | A modality-aware token-scoring + per-layer budget scheme to decide how much of an old screenshot's KV to keep vs evict, and evidence that vision-token KV is highly compressible without much accuracy loss. |
| Scissorhands: Exploiting the Persistence of Importance Hypothesis for LLM KV Cache Compression at Test Time | NeurIPS 2023 | The persistence assumption and a probabilistic-retention scheme to carry importance scores forward across agent steps, reducing the risk that a single noisy step evicts a span we will need again. |
| SnapKV: LLM Knows What You are Looking for Before Generation | NeurIPS 2024 | The observation-window selection mechanism and the pooling trick (keep clustered spans, not top-k scattered tokens) — directly portable to choosing the [p0,p1) image spans we retain before applying the renumber/K-shift. |
| Model Tells You What to Discard: Adaptive KV Cache Compression for LLMs (FastGen) | ICLR (Oral) 2024 | A per-head policy-selection recipe driven by a cheap one-pass profile, letting us set heterogeneous eviction budgets per head instead of a single global last-3 rule. |
| Quest: Query-Aware Sparsity for Efficient Long-Context LLM Inference | ICML 2024 | A query-aware page-criticality estimator (min/max key bounds + query dot-product) we could adapt to skip stale screenshot pages at attention time WITHOUT touching positions — sidestepping the M-RoPE renumber risk entirely if memory (not compute) is the only constraint. |
| GUI-KV: Efficient GUI Agents via KV Cache with Spatio-Temporal Awareness | arXiv preprint (Salesforce AI Research) 2025 | Two ready-to-borrow scores: L2-norm-augmented attention for spatial saliency, and key-subspace-projection redundancy across frames to identify droppable historical screenshot tokens — the victim-selection front-end to our in-cache eviction. |
| Efficient Long-Horizon GUI Agents via Training-Free KV Cache Compression (ST-Lite) | arXiv preprint (cs.CV) 2026 | A component-aware (keep whole UI elements) saliency rule plus a trajectory-level dedup gate to prune repeated screenshots across steps — directly usable to choose which screenshot spans we retain in a bounded cache. |
| Efficient Memory Management for Large Language Model Serving with PagedAttention | SOSP (ACM Symposium on Operating Systems Principles) 2023 | Block-table indirection: the ability to free/remap individual KV blocks (one screenshot's span) without touching the retained context's blocks — the structural prerequisite for in-cache eviction with a per-step hit on what remains. |
| SGLang: Efficient Execution of Structured Language Model Programs (RadixAttention) | NeurIPS (Conference on Neural Information Processing Systems) 2024 | An LRU radix-tree index + cache-aware scheduler design we can adapt to track the per-step retained-context prefix and decide eviction order across screenshots, instead of evicting blindly at the prompt level. |
| LMCache: An Efficient KV Cache Layer for Enterprise-Scale LLM Inference | arXiv preprint (open-source system; integrates with vLLM Production Stack) 2025 | A real connector/tiering interface (and the CacheBlend integration path) into which a libllama-level 'evict-and-K-shift the old screenshot span' operation could be wired, plus the empirical hit-rate-collapse-under-truncation evidence (85%->45%) that frames our contribution. |
| Cost-Efficient Large Language Model Serving for Multi-turn Conversations with CachedAttention (AttentionStore) | USENIX ATC (Annual Technical Conference) 2024 | A concrete prior for 'reuse cached KV after the surrounding context's positions changed' — the conceptual ancestor of our M-RoPE-aware K-shift — plus the layer-wise prefetch/overlap scheme to hide KV reload latency across agent steps. |
| Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving | USENIX FAST (Conference on File and Storage Technologies) — Best Paper 2025 | A KVCache-centric scheduling and tiered-pool blueprint for deciding which screenshot spans to keep resident, offload, or evict across an agent rollout, and how to meet a per-step latency SLO while doing so. |
| STaR-KV: Spatio-Temporal Adaptive Re-weighting for KV Cache Compression in GUI Vision-Language Models | arXiv preprint 2026 | A per-head spatial-profiling + temporal-stability scoring scheme to rank screenshot tokens for eviction, and an up-to-date baseline on UI-TARS-1.5-7B and OpenCUA-7B across four GUI benchmarks (ScreenSpot-Pro, ScreenSpot-v2, AndroidControl, AgentNetBench) for head-to-head comparison. |
| Qwen2-VL: Enhancing Vision-Language Model's Perception of the World at Any Resolution (M-RoPE origin) + Qwen3-VL Technical Report (Interleaved-MRoPE lineage) | arXiv technical reports 2024 | The exact M-RoPE position-id layout per screenshot (the [p0,p1) image span structure) we must track from the mtmd injection, plus the documented NEOX-as-temporal-shift trick (theta=-1) and its position constraint that our renumber-and-K-shift implementation must respect. |
| Efficient Streaming Language Models with Attention Sinks (StreamingLLM) | ICLR (International Conference on Learning Representations) 2024 | The position-renumbering-in-cache principle (cache-relative positions + RoPE re-indexing) and the attention-sink rationale for pinning the prompt prefix — the exact recipe llama.cpp's llama_memory_seq_add + K-shift implements, which we extend to M-RoPE. |
| An Image is Worth 1/2 Tokens After Layer 2: Plug-and-Play Inference Acceleration for Large Vision-Language Models (FastV) | ECCV (European Conference on Computer Vision) 2024 | An empirical layer threshold and attention-score criterion for how/where image-token KV becomes droppable, and the 'visual information migrates to text early' justification for retaining the text/action history while evicting the image span. |
| Efficient Inference of Vision Instruction-Following Models with Elastic Cache | ECCV (European Conference on Computer Vision) 2024 | An anchor-point KV-merging primitive as a fallback/complement to span eviction (merge old screenshot KV instead of dropping it), plus the instruction-vs-generation stage separation for budgeting. |
| UI-TARS: Pioneering Automated GUI Interaction with Native Agents | arXiv technical report 2025 | The reference agent-loop and OSWorld evaluation framing (multi-screenshot observation history, unified action space) and a quantitative SOTA anchor to position the quality/latency trade-offs our eviction targets. |
Measured live on wuklab-NUC16 (Core Ultra 7 356H, 96 GB, llama.cpp CPU, Holo3-35B-A3B i1-Q4_K_M). Mechanism grounded in the local llama.cpp source; prior art verified against primary sources. Companion analysis: KV-cache & accelerator study.