GLM-5.3-Flash (320B MoE) in EXL3 TR3 4bpw, tensor-parallel across four DGX Spark nodes
(GB10, 121.7 GiB unified memory each), vLLM 0.28.1rc1.dev617 on a pinned upstream
commit (83252ea899) plus a twelve-patch persistence series, DFlash2 speculative
decoding at k=7, --enforce-eager, fp8 KV, MAX_NUM_SEQS=4. The disk
tier is per-rank NVMe with a sqlite index and per-rank coordinators. The serving
configuration is unchanged from the published TP4 playbook; everything described here is
additive.
| persistence OFF | write-behind ON (this deployment) | |
|---|---|---|
| Addressable session context | 3.39M tokens (GPU pool only) | ~47M tokens capacity; ~6.9M warm today; sessions survive eviction |
| Cold prefill 64k / 256k | 2,028 / 1,901 tok/s | 2,026 / 1,919 tok/s — parity (the 256k cell even served 16,128 tokens from disk mid-prefill) |
| Decode 64k / 256k (C=1) | 54.5 / 51.0 tok/s | 52.5 / 44.5 tok/s — within run noise except deep-context under pressure |
| 200k session, repeat visit | 112 s every time | 3.0 s from cache; 1.42 s from disk at the tested sizes |
| 3.6M-token flood (> GPU pool) | overflow recomputes, sessions lost | absorbed: 2 GB written, 4–11 declines, zero stalls; evicted sessions restorable — eager mode wrote 74 GB with 228 declines for the same flood |
| Idle disk traffic | — | zero (pressure gate) + hourly stale-content flush at background rate |
All cells measured with unique salted prompts, streaming TTFT, medians of two reps or better; engine variance ±5–10%. Protocols and probe scripts are in the repo.
The first version of this tier stored eagerly — every new chunk written on the request path, responses held for the store drain, synchronous all-rank admissions. It worked, and it taxed exactly the traffic it should protect: −11…−38% prefill, −37% decode at 256k, 36× write amplification. The no-tax property came from five decisions, each taken after measurement:
Two engineering disciplines carried the campaign: the patch series is hash-pinned (before/after hashes per file, an AST suite binding the patched methods and running them engine-free), and every measured claim above has a committed probe. The flood-crash and fence-cleanup bugs found in bring-up were caught by that suite or its live smoke — the suite is part of the design, not an afterthought.
| Context | C | Metric | OFF | eager (retired) | write-behind |
|---|---|---|---|---|---|
| 8k | 1 | prefill tok/s | 1,868 | 1,531 | 1,868 |
| 64k | 1 | prefill tok/s | 2,028 | 1,531 | 2,026 |
| 256k | 1 | prefill tok/s | 1,901 | 1,691 | 1,919 |
| 64k | 1 | decode tok/s | 54.5 | 46.0 | 52.5 |
| 256k | 1 | decode tok/s | 51.0 | 32.5 | 44.5 |
400 unique 9k sessions (3.6M tokens) against the 3.39M-token pool, then a re-request of an early session while the engine is busy:
| eager (retired) | write-behind | |
|---|---|---|
| Written during flood | 73.8 GB | 2.07 GB |
| Allocation declines | 228 | 4–11 |
| Restore of evicted 9k session | 4.15 s / 1.03 GB | 1.42 s / 341 MB |
| Engine state after | healthy | healthy, zero stalls |
KV pool deliberately capped to 944,871 tokens (12 GiB, ~28% of normal) so eviction is continuous. A 200k session (21% of the pool) was seeded, then the fleet carried ten minutes of sustained C=4 production-shape load (rotating unique 8k–32k prefills, 300-token decodes) followed by a 16×120k eviction flood and a cold restart:
| Phase | Result |
|---|---|
| Sustained C=4 under continuous eviction | 43/43 requests, zero errors; decode median 56.0 tok/s; per-stream prefill 306 tok/s (4-way split) |
| 200k re-request mid-bench | 109 s (session churned out of the small pool; partial disk service, remainder recomputed) |
| Eviction flood (16×120k) | 16/16 OK, engine healthy |
| 200k reload from disk, cold (post-restart) | 102.9 s — full recompute; zero bytes read from disk (census). On a small, continuously-busy pool the bounded capture window (16k holds / 16 keys-per-step) loses the whole-session race. |
| Immediate repeat (hot) | 2.9 s, 200k tokens from cache |
Read together with §4.2: whole-session disk restore is proven at 9k (1.42 s) and as mid-prefill partials; at 200k under sustained pressure the honest result is partial-to-none, by the design’s bounded-write economics — the fix is the flush command (§6) or sized windows, not a defect. Concurrency behaviour itself was clean throughout: no stalls, no errors, decode at parity under eviction load.
Local Inference Labs standard bench (C1–C6, 700-token outputs, salted prompts): 38.3 / 73.4 / 51.6 / 52.9 / 64.3 / 69.2 aggregate tok/s, zero failures — within variance of the published no-persistence baseline; the tier does not disturb the standard bench.
Production smoke (agentic ladder, 300-token outputs): 32k → 15.4s TTFT, 2,030 prefill
tok/s; 128k → 66.6s, 2,008; 256k → 141s, 1,897; 400k (404,745 tokens, the largest
single request this fleet has served) → 261s, 1,549 tok/s, decode healthy; a 4×32k
concurrent burst ran clean at 393–1,396 prefill tok/s per stream. The configured
max_model_len of 850k is refused at admission in 1.1s — the practical
single-request ceiling is ~405k tokens, set by unified memory, independent of
persistence; whether the baseline playbook shares that wall has not been measured and
should be (same ladder, persistence off).
Full cold restore of large sessions from disk. Disk restore is proven at 9k
(1.42 s) and as a 423,936-token partial inside a live 800k prefill, and cache retrieval
is proven at 200k (3.0 s). A complete 200k+ session restored cold from disk after a
restart recomputes today: the lookup traces show the earliest chunks absent, and the
census shows why — under a heavy flood the bounded capture window (4,096 held blocks,
8 keys/step drain) lands gigabytes, not the whole evicted set, and the mamba groups'
chunks are visible to the store but not to the flusher's scan population. The dials
exist (eviction_hold_cap, eviction_store_per_step,
idle_flush_per_scan) and the mechanism is proven in both directions; whole-
session coverage at flood scale is engineering, not architecture. Until it lands, quote
disk restore at the tested sizes.
# engine: vLLM 83252ea899 + patches/persistence-flash/0001..0013 (hash-pinned manifest; # AST suite test_native.py, 23 tests, runs engine-free) # package: persistence/recipe_persistence (bind-mount overlay) # configs: PERSISTENCE=on PERSIST_STORE_MODE=evict_only # PERSIST_MIN_DISK_LOOKUP_TOKENS=32768 PERSIST_LOOKUP_KEYS_PER_STEP=2048 # PERSIST_EVICTION_STORE_HIGH_WATERMARK=<~20% pool blocks> # pressure gate # PERSIST_IDLE_FLUSH_STALE_SECONDS=3600 / _PER_SCAN=32 / _SCAN_SECONDS=5 # measure: python3 benchmark/bench_c1c6.py --url http://<head>:8888 --model <name> --rounds 3 python3 benchmark/ab_matrix.py --modes off,evict --sizes 8192,65536,262144 --conc 1,4 python3 benchmark/probe_evict_refill.py --n 400 --tokens 9000 --settle 45
Public lane: github.com/hughmadden/GLM-5.3-Flash-NVFP4-1M-KV-4x-DGX-Spark
under exl3-persistence/. Sydney timestamps throughout.
Full per-component attribution in the repository's CREDITS.md. The persistence tier — patches, package, probes, this report — is Turquoise Bay AI's additive work, committed with hash-pinned provenance.