Files
onion-mc/phase0/P0-steamdeck.md
T
logan 611a1a5952 docs: client-perf analysis, bench harness and work journal
Everything the next agent needs to run the Phase 2 optimisation loop on a
machine that can launch the client:

- analysis/client-perf/: LEVERS (ranked levers + corrections), BENCH-MATRIX
  (world, scenes, config IDs, blocks B0-B14 with decision rules),
  PLAYER-TUNING, SPAWN-TUNING, research briefs, the jar scanner and its
  output, observed default configs, and proposed-configs/ (build.py
  generates tiers and bench variants and fails on unknown keys;
  apply_variant.py applies a variant and merges options.txt).
- analysis/client-perf/bench/onion-bench/: bench-world datapack (scene
  teleports, Create grid, mob pen, sound storm, 120 s teleport tour).
- analysis/audit/: the static recipe/dependency audit, including gen_fixes.py,
  which generates the shipped Paxi datapack and was never tracked.
- phase0/: per-machine measurement harness (Steam Deck, 7700K/1060,
  6700K/1080 Ti).
- .pi/journal.md: running work log; read it first.

All of it is packwizignored, so nothing here ships to players.
2026-10-14 18:15:32 -04:00

250 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.