`--batched-session N`: a request that shares only the system prompt with a live slot evicts it instead of taking an empty slot
Build: antirez/ds4 main 8db1d1d, Metal, M4 Max 64 GB, macOS 26.6.2
Model: Qwen3.8-Flash-Next-Q2.gguf (self-contained), --metal -c 131072 --prefill-chunk 1024 --mtp --batched-session 2 --kv-disk-dir ... --kv-disk-space-mb 65536
(also reproduced at -c 163840)
Symptom
With two resident slots and two independent chat conversations that share the same system prompt
(11K tokens) but nothing else, sending them one after the other never uses the second slot.
Each request lands in the slot holding the other conversation, evicts it to disk, and restores its
own state from disk. --batched-session 2 then behaves exactly like one slot:
14:54:02 live kv cache miss live=80268 prompt=90076 common=11154 vision=match reason=token-mismatch
14:54:02 kv cache stored tokens=80268 ... reason=evict
14:57:05 live kv cache miss live=90166 prompt=90178 common=11154 vision=match reason=token-mismatch
14:57:05 kv cache stored tokens=90166 ... reason=evict
14:57:05 kv cache hit text tokens=80268 ... load=... msSlot 2 was empty throughout. It only gets populated when two requests are in flight at the same time (slot 1 busy), after which both conversations stay resident and alternate with no misses, so the steady state is fine; only the cold start is wrong.
Over 8 alternating turns (A at 70K→120K, B at 80K→130K, 10K new tokens each): one slot = 23–26 s/turn; two slots from cold = 24–28 s/turn (8 misses, 8 restores); two slots after one concurrent round = 21–22 s/turn (0 misses).
Cause
job_slot_score() (ds4_server.c:14642) scores an idle slot by
ds4_session_common_prefix(slot->session, &j->req.prompt) (line 14676). An empty slot has no tokens,
so it scores 0. A slot holding an unrelated conversation scores the length of the shared system
prompt (here 11,154). dispatch_jobs_locked() picks the highest score with a strict >, so the
occupied slot always wins over the empty one whenever the conversations share any prefix, which with
a fixed system prompt is always.
Repro
Two OpenAI-compatible chat conversations with the same system prompt and different histories
(≥ 20K tokens each so the miss is visible in timing). Send A, then B, then A, then B, sequentially.
Expect: no live kv cache miss after the first turn of each. Observe: one on every turn, and
--batched-session 2 never logs work in the second slot until two requests overlap.
Harness used: a Hermes-shaped tool-call session bench; happy to share.
Source: antirez/ds4