# Phase 0 — P0: Steam Deck Setup and measurement procedure for the lowest-end test machine in the Onion MC client tuning fleet. --- ## Profile | | | | --- | --- | | CPU | AMD Zen 2, 4 cores / 8 threads, 2.4–3.5 GHz | | GPU | AMD RDNA2 (Van Gogh), 8 CU, integrated | | RAM | 16 GB LPDDR5, **shared with the GPU** | | Display | 1280×800 — LCD is 60 Hz, OLED is 90 Hz | | OS | SteamOS (Arch-based, read-only rootfs) | | **Binding constraint** | GPU compute, memory bandwidth, shared memory pressure | | **What this tier tests** | The floor. If the ladder holds here it holds anywhere. | | **Expected DH answer** | Off, or the minimum viable preset | ### Determine your panel The LCD panel is 60 Hz. **If this is an LCD Deck, targets of 120 and 144 are meaningless on this machine** — it can only validate the 30 and 60 rows of the ladder. Record which panel you have; it changes what this machine can prove. --- ## Shared measurement protocol Applies to every machine in the fleet. Duplicated here so this document stands alone. 1. **Uncapped, vsync off** during measurement. Apply the FPS cap only *after* tuning. With a cap or vsync active, every configuration "hits" the target and the ladder never fires. 2. **Metric is p99 frametime and 1% low, not average FPS.** 3. **Discard 10–15 s of warmup** per scene — JIT, chunk load, initial GC. 4. **Settle after any render-distance or DH change.** Both trigger rebuilds; measuring immediately measures the rebuild, not the steady state. 5. **Three runs per configuration, report the median and the spread.** A single run of anything is noise. 6. **One variable per run.** If you change two things, you have learned nothing. 7. Guardrails: if the FPS limiter is active, the governor moved, or RAM headroom changed materially, the run is invalid — discard rather than interpret. --- ## Step 1 — Preconditions - [ ] Plugged into the charger. Battery vs. AC changes APU power behaviour. - [ ] Switch to **Desktop Mode**. All measurement happens here, launching Prism from a terminal. Gaming Mode routes the overlay through MangoApp, which cannot log. - [ ] Instance installed on **internal storage**, not a microSD card. Card I/O affects chunk loading and DH LOD reads. - [ ] Confirm panel refresh rate and record it. ## Step 2 — Disable the competing overlay SteamOS's built-in performance overlay is **MangoApp**, not MangoHud. It is an IPC bridge and **cannot write CSV logs**. Running it alongside MangoHud produces two stacked overlays and aborts logging. - [ ] Quick Access Menu (`...`) → **Performance** - [ ] **Performance Overlay Level → 0** - [ ] **Framerate Limit → Off** (critical — otherwise every config "hits" the cap) - [ ] **TDP Limit → Off**, or pin it to a fixed value (e.g. 15 W) and never change it between sessions. Whichever you choose, record it and keep it constant. - [ ] Check that no per-game profile is re-enabling any of the above. - [ ] If Decky Loader is installed, disable any MangoHud/benchmark plugin that routes through MangoApp. ## Step 3 — CPU governor and thermals The Deck's governor is normally `schedutil`. Two options: - **Recommended:** leave it as SteamOS sets it, but *record* it (`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor`) and keep it identical across every session. - Pinning `performance` gives more consistent clocks but increases heat on a handheld, which risks thermal throttling — usually a worse trade for repeatability. **Thermal soak:** let the Deck play for ~5 minutes before the first measured run. A cold Deck boosts then throttles; the first runs of a session are not representative. This is the single biggest source of bogus deltas on this machine. ## Step 4 — Install MangoHud SteamOS's rootfs is read-only, and anything installed via `pacman` can be removed by a SteamOS update. Re-check this before every session. ```bash sudo steamos-readonly disable sudo pacman -S --needed mangohud sudo steamos-readonly enable ``` Then find the actual paths — **do not assume them**: ```bash pacman -Ql mangohud | grep -E 'mangohud$|libMangoHud' ``` This tells you the wrapper binary and the shared library path. Note them; you will need them if the wrapper route fails. > **Alternative if you don't want to touch the rootfs:** MangoHudPy is built for > SteamOS/Bazzite and manages MangoHud configs and log uploads. Verify it can write CSV > logs before relying on it — some SteamOS MangoHud tooling routes through the MangoApp > IPC shim, which explicitly cannot write logs. ## Step 5 — MangoHud configuration Generate the config from the packaged example rather than trusting a transcription: ```bash mkdir -p ~/.config/MangoHud ~/mcbench/logs cp /usr/share/doc/mangohud/MangoHud.conf ~/.config/MangoHud/MangoHud.conf # verify path with pacman -Ql ``` Then set these keys in `~/.config/MangoHud/MangoHud.conf`: ```ini output_folder=/home/deck/mcbench/logs # required for logging autostart_log=1 # start logging automatically log_duration=30 # seconds; match your scene length fps_limit=0 # uncapped frametime=1 frame_timing=1 # percentiles: see the packaged example for the exact key/syntax — it defines a # '+'-separated list of percentiles emitted in the benchmark summary ``` Confirm the exact percentile key name against the packaged example file. Logging can also be toggled at runtime (`toggle_logging`, default `Shift_L+F2`). ## Step 6 — Launcher and JVM Use **Prism Launcher** (or ATLauncher) with the pack imported, then launch it from a terminal in Desktop Mode so the environment is under your control. **Java:** 21 (Arch `jre21-openjdk` or Temurin 21). Use the **same JVM build across all three machines** where possible — different JVM builds are a confound. **Wrapper command** — Prism → *Edit Instance → Settings → Custom Commands → Wrapper command*. This is the most reliable way to hook the Java process directly: ``` mangohud ``` If no overlay appears, or Minecraft fails to start, try: ``` mangohud --dlsym ``` **JVM arguments** (held identical across all three machines; only `-Xmx` differs): ``` -Xmx5G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 ``` **On `-Xmx5G`:** the Deck's 16 GB is shared with the GPU, so heap is not free. Start at 5 G, never exceed 6 G, and treat the final value as a Phase 0 *output* derived from GC data, not a guess. Omit `-XX:+AlwaysPreTouch` here — committing the whole heap up front costs memory you may not have. ## Step 7 — Pin the in-game settings These are **controlled variables**. Set them once, record them, and do not change them between runs unless the run is specifically testing that setting. - Graphics: Fancy - Render distance: 8 (matches the server's `view-distance`) - Particles: All - Clouds: Fancy - Entity shadows: On - Biome blend: fixed value, recorded - Mipmap levels: 4 - GUI scale: fixed number (not Auto) - **Max framerate: Unlimited** - **VSync: Off** - FOV, resolution, fullscreen mode: fixed and recorded ## Step 8 — Verification run Prove the harness works before collecting any real data. - [ ] Launch the pack from Prism with the wrapper command set. - [ ] Confirm the MangoHud overlay appears over Minecraft. - [ ] Load the benchmark scene, play 30 s. - [ ] Confirm a CSV file appeared in `~/mcbench/logs`. - [ ] Open the CSV and confirm it contains a frametime column. - [ ] Run the same configuration three times and check the spread. **If the spread is large, nothing downstream is trustworthy** — fix that before continuing. ## Step 9 — Per-session checklist - [ ] Charger connected - [ ] Desktop Mode - [ ] SteamOS overlay level 0, FPS limit off, TDP as recorded - [ ] Governor matches previous sessions - [ ] MangoHud still installed (SteamOS update may have removed it) - [ ] 5-minute thermal soak completed - [ ] CSV output folder writable ## Step 10 — Recording sheet Log one row per run: | Field | Example | | --- | --- | | Date / session | 2026-09-28-a | | Machine | P0-SteamDeck-LCD | | Config ID | baseline / dh-off / emf-off / … | | Scene | A-base / B-terrain / C-gui | | Run # | 1 / 2 / 3 | | CSV file | `Minecraft_2026-09-28_14-22-01.csv` | | p50 / p95 / p99 frametime (ms) | | | 1% low FPS | | | Avg FPS | | | Peak measured frametime (ms) | | | Notes | e.g. "thermals settled", "DH disabled" | --- ## Machine-specific caveats - **The overlay trap.** SteamOS gives you MangoApp, which looks like MangoHud and cannot write logs. Getting CSV requires launching through the MangoHud wrapper, in Desktop Mode, not through Gaming Mode. - **VRAM is not measurable here.** The GPU shares system memory, so there is no separate VRAM number to track. Watch total system RAM and swap instead; memory pressure is what you will actually see. - **SteamOS updates remove `pacman`-installed packages.** Verify MangoHud exists at the start of every session. - **60 Hz panel (LCD) cannot validate 120/144 targets.** Document this rather than pretending those rows are tested. - **Smallest thermal envelope of the fleet.** The warm-up soak is not optional. - **Per-core performance is much lower than the other two machines** despite the identical 4C/8T topology. Do not assume a CPU-side result from P1/P2 transfers here at the same magnitude — only the direction should be expected to match.