# 02 — sizes, streaming speed evidence, performance model & measurement plan

## 3. sizes [est]

expert = 4.915M params. totals across 48 layers:

| experts/layer | IQ2_XS (2.31 bpw) | Q2_0 (**2.25 bpw** [src: `ggml.h` type 42, 64w=18B]) | Q3_K / IQ3_S (3.44 bpw) | IQ3_XXS (3.06 bpw) |
|---|---|---|---|---|
| 512 | 34.9 GB | **34.0 GB** | 51.9 | 46.2 |
| 320 | 21.8 | **21.2** | 32.4 | 28.9 |
| 256 | 17.5 | **17.0** | 26.0 | 23.1 |
| 224 | 15.3 | **14.9** | 22.7 | 20.2 |

other fixed costs:
- dense ≈ 3.2 GB
- KV at 128K: fp16 3.0 GiB, q8 1.6 GiB, q4 0.84 GiB
- GDN state ≈ 110 MiB (fp32)
- mmproj ≈ 0.5–0.9 GB

fast-memory budget for experts:
- desktop: ~4.3 GB VRAM + ~7.5 GB RAM ≈ 11.8 GB ≈ 178 experts/layer at Q2_0 (1.3824 MB/expert)
- laptop: ~7.5 GB ≈ 113 experts/layer at Q2_0
- so on both machines, even 224 is partly streamed from SSD

desktop note: Strata needs ≥32 GB system RAM [src: Strata MODELS.md, web], and the measured 7600 XT run had 64 GB. **16 GB RAM is the desktop bottleneck, not the GPU.** options:
- (a) more RAM
- (b) Strata/llama.cpp low-RAM mode with heavier SSD streaming
- (c) prune harder for the desktop

---

## 4. what's known about streaming speed

### 4.1 Mac evidence [src: Strata docs/MAC.md, the only streamed-Mac measurement]
M4 Mac mini, 32 GB, experts streamed, 11.5–14.7 GB arena, no MTP, medians of 5:

| | Q2_0 | IQ3_XXS |
|---|---|---|
| decode, short | 14.1 | 10.0 |
| decode after 6K doc | 13.1 | 7.7 |
| prompt, 4K tokens | **93.6** | **65.8** (84.1 with experts' copy) |

- M5 Max 128 GB, resident: Q2_0 prompt ~1,430 tok/s at 4K, decode 87 tok/s without MTP.
- Slotstream [src]: 24–48 GB Macs, decode ~5–16 tok/s (est. table), 20.9–23.7 tok/s on a 48 GB M5 Pro. no prefill numbers.

### 4.2 ds4-recipe evidence [src: tangled.org/astrra.space/ds4-recipe]
DeepSeek V4.1 Flash, Strix Halo 128 GB UMA, 3 NVMe, ~31% of experts resident:
- cold prefill 354–391 tok/s (README says ~450 now), from:
  - 4 lanes × 8,192-token chunks sharing one read of each layer's expert union
  - hipBLASLt prepared GEMMs
- **p50 prefill by turn size**:

| new tokens in turn | p50 tok/s |
|---|---|
| 64–256 | 19 |
| 256–1k | 46 |
| 1k–4k | 106 |
| 4k–16k | 236 |
| 16k+ | ~340 |

small turns are SSD-bound.

### 4.3 Air thermals & local M5 hardware microbench [src: local `bench/README.md` + web]
- **measured on this 13" M5 Air (`Mac17,3`, 10-core GPU, 1 TB SSD, `bench/run_01..03`):**
  - **M5 10-core GPU FP16 GEMM (`K=2560`):** **12.60 TFLOP/s** at M=512, **13.66 TFLOP/s** at M=1024, **14.07 TFLOP/s** at M=4096 (`recommendedMaxWorkingSetSize = 17.76 GiB`). exactly 1/4 of the 40-core M5 Max, confirming the **~356–360 tok/s** resident prefill compute ceiling.
  - **60-second continuous GPU thermal sag test (`M=4096, K=2560, N=2560` FP16):** started at **14.00 TFLOP/s** (`t=0..15s`) and ended at **13.88 TFLOP/s** at `t=55..60s` (**−0.86% sag over a full minute**). so single-prompt cold prefills (even 15–30 s) do not hit a thermal cliff; multi-minute sustained loads [web: Notebookcheck ~9 W sustained] still favor KV reuse.
  - **1 TB SSD uncached read bandwidth (`F_NOCACHE=1`, 100.0% physical `disk0` verified via `iostat -Id` on virgin 1 GiB slices):**
    - standard GGUF (`512 KiB` × 3 reads/expert): **2.41 GB/s** (1 thread) → **5.52 GB/s** (2 threads) → **7.03 GB/s** (4 threads)
    - contiguous `.experts` copy (`1.5 MiB` × 1 read/expert): **3.85–3.93 GB/s** (1 thread) → **6.84 GB/s** (2 threads) → **6.60–6.89 GB/s** (4 threads)
    - PLE n-gram table (`4 KiB` random page reads): **0.04 GB/s** (~10k IOPS, ~1.6 ms/tok for 16 heads) at 1 thread → **0.33 GB/s** (~82k IOPS, ~0.2 ms/tok) at 8 threads
  - **methodological trap caught (`run_02` → `run_03`):** on macOS APFS, repeating `pread` on identical file offsets across benchmark iterations can partially hit APFS cache on pass 2+ even with `F_NOCACHE=1`. always use virgin slices and check `iostat -Id` (`disk0` MiB delta == 100% of requested MiB).

---

## 5. performance model [est, to be replaced by measurements]

### 5.1 the metric: per-turn floor
- each prefill chunk (or each turn, however short) reads, for every layer, the union of experts its tokens picked. with top-10 of 512, even ~256 tokens touch most of a layer (uniform-routing approximation; real routing is skewed, so less).
- so **per-turn floor ≈ non-resident expert bytes ÷ SSD read rate**, plus compute.
- kernel opts move the ceiling. pruning, residency and MoCE move the floor.

### 5.2 laptop model (anchored to measured M5 Air SSD & GPU constants)
inputs:
- Q2_0 (2.25 bpw = **1.3824 MB/expert** [src: `ggml.h` type 42]), ~7.5 GB experts resident (~113 experts/layer)
- compute ceiling **356 tok/s** [src: local Metal FP16 GEMM **14.07 TFLOP/s** on M5 10-core GPU, scaled from M5 Max 1,430 tok/s @ 40c]
- measured SSD rates on this 13" M5 Air (`iostat -Id` 100% physical `disk0` verified) [src: `bench/README.md`]:
  - **2.41 GB/s**: 1-thread standard GGUF (3 × 512 KiB/expert)
  - **3.90 GB/s**: 1-thread contiguous `.experts` copy (1 × 1.5 MiB/expert)
  - **6.80 GB/s**: 2–4 thread `pread` fan-out (saturates PCIe Gen4 x4 NVMe)
- no IO/compute overlap (pessimistic), before MoCE (measured Phase 1b OOS `lru` `λ = 0 -> 0.09` with `protect_top_j = 3` cuts decode misses **17.4–19.9%** on its own, or **−36.4% at `K320_reap_hybrid` / −47.4% at `K256_reap_l2_sum`** combined with pruning; see §7.1 for exact OOS decode tok/s)

| experts (non-resident Q2_0 @ 2.25 bpw) | SSD mode (measured) | 1024 chunk | 4096 | 8192 | 256-tok cold prefill floor (pre-MoCE) |
|---|---|---|---|---|---|
| 512 (26.5 GB) | 2.41 GB/s (std 1-th) | 74 tok/s | 182 | 241 | ~11.7 s |
| 512 (26.5 GB) | 3.90 GB/s (`.experts` 1-th) | 106 | 224 | 275 | ~7.5 s |
| 512 (26.5 GB) | 6.80 GB/s (2–4 th) | 151 | 266 | 304 | ~4.6 s |
| 320 (13.7 GB) | 3.90 GB/s (`.experts` 1-th) | 160 | 273 | 309 | ~4.2 s |
| 320 (13.7 GB) | 6.80 GB/s (2–4 th) | 209 | **303** | 327 | **~2.7 s** (warm 256-tok decode: `5.88 s` @ `43.5 tok/s` w/ MoCE) |
| 256 (9.5 GB) | 3.90 GB/s (`.experts` 1-th) | 193 | 294 | 322 | ~3.2 s |
| 256 (9.5 GB) | 6.80 GB/s (2–4 th) | 240 | **318** | 336 | **~2.1 s** (warm 256-tok decode: `5.40 s` @ `47.4 tok/s` w/ MoCE) |
| 224 (7.4 GB) | 3.90 GB/s (`.experts` 1-th) | 215 | 306 | 329 | ~2.6 s |
| 224 (7.4 GB) | 6.80 GB/s (2–4 th) | 259 | **325** | 340 | **~1.8 s** (warm 256-tok decode: `5.01 s` @ `51.0 tok/s` w/ MoCE) |

reading:
- 200 tok/s on cold prompts is mostly a chunk-size question
- pruning mostly buys the per-turn floor
- Air throttling will pull sustained cold prefill down (guess 150–250 tok/s, unmeasured)
- design implication for the Air: maximize reuse so the GPU only works in short bursts (disk KV cache, SCR, preserved thinking)

### 5.3 decode
- per token reads ~1.5–2 GB of weights [est] vs ~150 MB of context-dependent traffic at 128K (QSA KV ~50 MB + indexer scan ~100 MB)
- Strata RTX 5070: 94 → 76 tok/s from short to 128K [src]
- on the Air, decode is dominated by SSD misses (~14 tok/s measured on M4 vs ~80 tok/s bandwidth bound)
- so MoCE / residency / prefetch matter. attention tricks don't.

---

## 6. measurement plan

principle:
- **Colab measures hardware-independent quantities** (quality, routing, misses per token/turn under each policy)
- **the local machines measure hardware constants** (SSD GB/s with the real read pattern, resident compute ceiling, thermals)
- multiply them to predict latency for every configuration, then validate only the top 2–3 for real

### 6.1 Colab (A100 80 GB)
1. setup:
   - HF token (Swift repos are gated)
   - download Swift GSQ-RCO IQ3_S (≈ 78 GB total; shard 1 resident in VRAM, PLE shard on disk via mmap/lazy)
   - build mainline llama.cpp with CUDA
2. **routing-trace logger**:
   - find the router-logit tensors in the qwen4exp graph (name unverified), hook them via the eval callback
   - log real agent sessions, prefill and decode, marked separately
   - format [est]: per token per layer, top-64 (expert id u16, logit fp16) = ~12 KB/token, so 1M tokens ≈ 12 GB. full 512-wide logits for a sampled subset only.
   - also log token ids, turn boundaries, session ids
3. **offline cache replayer** (CPU, can be written locally now):
   - policies: LRU, LFU, popularity EMA, EMA + near-pick credit, **inverse-router score**, Belady MIN (ceiling)
   - cache sizes matching each machine × each prune
   - output: misses per decoded token and per turn (by turn size), prefetch recall / read amplification for next-layer prediction
4. **pruning variants** 224 / 256 / 320:
   - saliency from our traces and/or RCO
   - GGUF slicing script
   - each variant ~40–60 GB: build → eval → upload to private HF → delete (disk is ~236 GB)
5. **quality evals** for each prune and each λ:
   - KL vs unpruned on held-out traces
   - JA probe
   - world-knowledge fabrication set **and** "said idk when it knew" set
   - persistent-agent evals (§6.4)
   - vision check (ISTA lesson)
   - persona style score (after the tune)
6. **MoCE λ sweep, closed loop**: simulate the cache inside the forward pass (routing depends on residency, so open-loop replay is wrong for λ > 0, as ds4 notes). λ ∈ {0, 0.05, 0.075, 0.1}, protect top-J ∈ {2, 3}.
7. **SCR staleness on GDN**: nats/token of SCR splices vs fresh prefill on real edited contexts.
8. prefix-sliding toggle and top-k 8 override: quality on the same evals.
9. teacher top-k logits + known/unknown labels for healing (phase 3).

### 6.2 laptop (phase 0, no training)
1. Strata-Metal (or Slotstream) running Swift GSQ-RCO Q2_0 / IQ2_XS with a persona system prompt
2. raw SSD read rate with expert-sized reads (and Strata's actual pattern)
3. resident compute ceiling: prefill on a small model / short prompt (gives the ~360 tok/s check)
4. cold prefill at 4K and 32K, chunk 1024 / 4096 / 8192 (if memory allows)
5. thermals: 3 back-to-back 32K cold prefills with `sudo powermetrics --samplers gpu_power`. watch tok/s sag and watts
6. decode at 4K / 64K / 128K context (tells us if prefix sliding has anything to win)
7. **seconds per agent turn at 500 / 2K / 8K fresh tokens**, warm cache
8. log two clocks: wall + server counters (REAP card lesson)
- early warning: if per-turn time is unusable even with reuse, revisit "same model on laptop" (§10)

### 6.3 desktop (phase 0)
- same list, on Strata HIP (gfx1102) or llama.cpp `--n-cpu-moe` + mmap, in low-RAM mode
- answers how bad 16 GB RAM really is


### 6.4 persistent-agent eval
what it's for: picking K, λ / top-J, the top-k 8 and prefix-sliding flags, accepting SCR's GDN error, and regression checks after healing / persona / FTPO. model-level metrics miss compounding errors over long tool loops (ISTA Coder: LiveCodeBench kept 98.7%, SWE-bench only 91.3% [src]).

1. **tier 1, fast screen (every variant):**
   - teacher-forced KL and top-1 agreement vs unpruned Swift on a fixed set of synthetic/curated persistent-agent traces (not personal session transcripts)
   - minutes per variant, no generation
2. **tier 2, task suite (finalists only), ~30–50 tasks with scripted pass checks, run through the real harness:**
   - **ops:** in a throwaway VM/container. e.g.: find why a systemd unit fails, fix a cron job, free disk, read logs and report, install and configure a package
   - **python-tool:** data wrangling, file inspection, quick calculations, the albedo-style kernel use pattern
   - **memory across sessions:** plant facts/preferences, run unrelated turns + a compaction, then check recall and correct use later. this exercises SCR + compaction.
   - **long-horizon persona consistency:** voice still right after 100K+ tokens and many tool outputs. judged by a rubric, plus the slop rate.
   - **abstention:** world-knowledge questions where the right move is "not sure" or a search call, plus ones it should just answer
   - **context-instruction following:** does it obey what the harness injects (memories, its own self-edited prompt rules, LCM/compaction summaries, tool protocols), including instructions that override the voice (exact formats, writing for other people, files/commits in a specified style). this replaces generic IFBench as the category that matters.
   - **JA** conversation and tool use
   - **vision** spot checks
   - existing benchmarks worth borrowing from (check licenses/fit): Terminal-Bench (ops), tau-bench (tool + user loops), LongMemEval / LoCoMo (long-term memory)
3. **report per variant:**
   - pass rate per category
   - the speed side from the latency model: seconds per turn for a typical turn mix, i.e. many small turns (user message, tool output), occasional compaction, rare cold starts

---
