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.
151 lines
29 KiB
Markdown
151 lines
29 KiB
Markdown
# Research: JVM, launcher, OS & driver levers — Onion MC client (NeoForge 1.21.1, Java 21, ~212 mods, Distant Horizons mandatory)
|
||
|
||
## Summary
|
||
For a DH-mandatory 200+ mod NeoForge 1.21.1 client, the single biggest platform lever is getting off stock G1 GC (Distant Horizons itself warns about it) onto either Generational ZGC (`-XX:+UseZGC -XX:+ZGenerational` on JDK 21) or Shenandoah, with heap sized to real headroom (5–6 GB on the 16 GB Deck and the 8 GB-free Linux box, 6–8 GB on the 32 GB Windows box) — oversizing costs more than it buys. Most OS/driver levers are small but cheap: `mesa_glthread=true` + `gamemoderun` on the Steam Deck, explicit `__GL_THREADED_OPTIMIZATIONS=0` on Linux NVIDIA (Sodium already sets it in source), and NVCP "Prefer maximum performance" on Windows. GraalVM is a benchmark-first experiment only: GraalVM for JDK 21 does not support Generational ZGC and real-world NeoForge 1.21.1 miscompiles exist.
|
||
|
||
---
|
||
|
||
## Findings
|
||
|
||
### 1. The GC baseline: G1 + why DH complains about it
|
||
- **NeoForge 1.21.1 requires Java 21**, so GC options are: G1 (default), Parallel (default for server-class? no—G1 default since JDK 9), Generational ZGC, Shenandoah. [NeoForge docs](https://docs.neoforged.net/) (DOCUMENTED).
|
||
- Vanilla ships its own G1 tuning in the client JSON: `-XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M`. Widely quoted from Mojang's version JSON. [Minecraft Forum](https://www.minecraftforum.net/forums/support/java-edition-support/3082919-jvm-arguments-using-g1gc-for-minecraft) (COMMUNITY, corroborated across 2 threads).
|
||
- **Distant Horizons logs at startup**: `[Render thread/WARN]: Distant Horizons: G1 Garbage collector detected. This can cause FPS stuttering. It's recommended to use a concurrent garbage collector like ZGC (Java 21+) or Shenandoah (Java 8 through 17) for a smoother experience.` DH is closed-source; exact wording verified from two independent log excerpts. [Minecraft Forum log](https://www.minecraftforum.net/forums/support/java-edition-support/3228579-modpack-randomly-losing-fps-and-sometimes-crashing), [New Eden modpack page quoting the warning](https://modrinth.com/project/7jwudrLZ) (DOCUMENTED — it is DH's own runtime warning). Newer DH writes it to the log only instead of an on-screen alert [Reddit r/ModdedMinecraft](https://www.reddit.com/r/ModdedMinecraft/comments/1pnk5uc/getting_this_message_every_time_i_launch_my_game/) (COMMUNITY). Mechanism is consistent with DH's large LOD allocations → G1 old-gen/mixed pauses = visible stutters (INFERENCE from the warning text + DH's memory behavior).
|
||
- Practical note: on Java 21, `-XX:+UseZGC` **alone** selects the *legacy non-generational* ZGC. Generational ZGC (what you want, and what "Java 21+" implies) needs `-XX:+UseZGC -XX:+ZGenerational`. Generational mode is only the *default* on JDK 23+ (JEP 474); non-gen was removed in JDK 24 (JEP 490). [OpenJDK ZGC wiki](https://wiki.openjdk.org/display/zgc/Main), [JEP 474](https://openjdk.org/jeps/474) (VERIFIED).
|
||
|
||
### 2. G1 tuned (Aikar-style) vs client
|
||
- Aikar's flags were tuned for Paper *servers* with large heaps (`MaxGCPauseMillis=200`, `G1NewSizePercent=30`…). [aikar.co via brucethemoose Benchmark.py](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks/blob/main/Benchmark.py) (DOCUMENTED origin, COMMUNITY applicability).
|
||
- brucethemoose (benchmarked repo, most credible MC flags source): Aikar's high `G1NewSizePercent` effectively clamps `MaxGCPauseMillis`, producing long stutters on some *clients*; clients also fill old gen far slower than a busy server. He ships a client-flavored G1 set: `-XX:+UseG1GC -XX:MaxGCPauseMillis=37 -XX:G1HeapRegionSize=16M -XX:G1NewSizePercent=23 -XX:G1ReservePercent=20 -XX:G1MixedGCCountTarget=3 -XX:G1HeapWastePercent=20 -XX:InitiatingHeapOccupancyPercent=10 -XX:G1RSetUpdatingPauseTimePercent=0 -XX:MaxTenuringThreshold=1 -XX:GCTimeRatio=99 …` [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED, benchmarked; **Java-17-era repo — revalidate on 21**).
|
||
- Expectation: tuned G1 remains the best default on **4C/8T CPUs with tight RAM** (P0, P2). It has no concurrent-cycle CPU tax like ZGC/Shenandoah. (INFERENCE from brucethemoose's guidance "G1GC on servers/clients with less RAM and fewer cores".)
|
||
|
||
### 3. Generational ZGC on JDK 21
|
||
- Flags for this pack on JDK 21: `-XX:+UseZGC -XX:+ZGenerational -Xmx<N>G` (+ optionally `-XX:SoftMaxHeapSize`, `-XX:ConcGCThreads`). [OpenJDK ZGC wiki](https://wiki.openjdk.org/display/zgc/Main) (VERIFIED).
|
||
- Sizing rule from the ZGC docs: heap must hold live-set **plus headroom for allocations while a cycle runs**; "in general, the more memory you give to ZGC the better", balanced against waste; `SoftMaxHeapSize` lets you cap heuristic target below Xmx. This makes ZGC a poor fit for P2 (only ~8 GB free RAM total) and marginal on the Deck's shared 16 GB. (VERIFIED docs + INFERENCE for fleet.)
|
||
- ZGC pauses are <1 ms regardless of heap, but it costs throughput: brucethemoose measured "a significant client FPS hit" from ZGC on an 8C/16T laptop, and notes ZGC wants *more* RAM and a raised `ConcGCThreads` cap (default = logical cores/4; he suggests 2 on 4-thread CPUs). [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED/COMMUNITY benchmark).
|
||
- DH's warning explicitly blesses ZGC as the primary fix; the DH community answer is always `-XX:+UseZGC` on Java 21 [r/MinecraftHelp NeoForge 1.21.1 thread](https://www.reddit.com/r/MinecraftHelp/comments/1svzilf/java_neoforge_1211_distant_horizons_g1_garbage/) (COMMUNITY).
|
||
- **GraalVM for JDK 21 does not support Generational ZGC** ("The following JDK 21 features are not available: JEP 439 Generational ZGC"). So GenZGC ⇒ a plain OpenJDK distro (Temurin et al.), not GraalVM 21. [GraalVM JDK 21 release notes](https://www.graalvm.org/release-notes/JDK_21/) (VERIFIED).
|
||
|
||
### 4. Shenandoah
|
||
- Not in Oracle JDK; available in Temurin/OpenJDK-based builds "from version 11 onward". [Red Hat Temurin docs](https://docs.redhat.com/en/documentation/red_hat_build_of_openjdk/21/html-single/getting_started_with_eclipse_temurin/index); not every build ships it — verify with `java -XX:+UseShenandoahGC -version` [Stack Overflow](https://stackoverflow.com/questions/73344814/openjdk-17-cant-use-shenandoahgc) (DOCUMENTED + caveat).
|
||
- brucethemoose's benchmarked verdict: **"I recommend Shenandoah on clients"**; flags `-XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGuaranteedGCInterval=1000000 -XX:AllocatePrefetchStyle=1`; it dislikes `AllocatePrefetchStyle=3`; mode/heuristic knobs changed little in his tests. [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED).
|
||
- Like ZGC it is concurrent, so it eats background CPU on 4C/8T — cheap stutter fix, small FPS tax. (INFERENCE.)
|
||
|
||
### 5. Heap sizing for a 200+ mod pack, and the cost of oversizing
|
||
- Prism's own wiki: "MORE RAM ALLOCATED DOESN'T MEAN BETTER PERFORMANCE! … a huge heap makes each garbage collection pause longer, which shows up in game as a stutter." [Prism Java settings wiki](https://prismlauncher.org/wiki/help-pages/java-settings/) (DOCUMENTED).
|
||
- brucethemoose: "Allocating too much memory can break gc or just slow Minecraft down, even if you have plenty to spare… allocate only as much as it needs (usually less than 8G)"; set `-Xms` = `-Xmx` **except** on low-RAM systems where Xms should stay below Xmx. [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED).
|
||
- For this pack: DH's LOD cache, Alex's Caves/Mowzie/Geckolib models and 212 mods plausibly put live-set near 3–5 GB with LODs loaded (INFERENCE — must be measured with Spark/F3). Recommended: **P0 5–6 GB, P1 6–8 GB, P2 5 GB max** (P2 has ~8 GB free for the whole OS+game). Oversizing harms: longer/less frequent G1 pauses, more RSS stolen from OS/page cache (fatal on 8 GB), ZGC cycles sweeping more memory. (INFERENCE, consistent with both sources above.)
|
||
|
||
### 6. `-XX:+AlwaysPreTouch` and Transparent Huge Pages (Linux)
|
||
- ZGC docs: if low latency is the goal, run Xms=Xmx and use `-XX:+AlwaysPreTouch` to page memory in **before** the app starts, avoiding commit/uncommit latency; uncommit can hurt latency. (VERIFIED: [ZGC wiki](https://wiki.openjdk.org/display/zgc/Main).)
|
||
- THP: `-XX:+UseLargePages -XX:+UseTransparentHugePages` issues `madvise(MADV_HUGEPAGE)`; requires kernel THP set to `madvise` in `/sys/kernel/mm/transparent_hugepage/enabled` (and, **for ZGC only**, `shmem_enabled=advise`). Some distros force `always`/`never` — check sysfs before benchmarking. (VERIFIED: [ZGC wiki](https://wiki.openjdk.org/display/zgc/Main).)
|
||
- brucethemoose: large pages "improve performance of Minecraft servers and clients"; on Windows they silently fail without admin/SeLockMemoryPrivilege — on Linux prefer `UseTransparentHugePages`. (DOCUMENTED: same README.)
|
||
- Cost: slower startup (pre-touch of full heap) and, with THP, potential memory bloat — risky on the 8 GB P2. Use on P1/P0, skip or test carefully on P2. (INFERENCE.)
|
||
|
||
### 7. GraalVM CE/EE (Oracle GraalVM) vs Temurin
|
||
- Since the "GraalVM for JDK 21" rebrand there is GraalVM Community Edition (free) and Oracle GraalVM; CE for JDK 21 exists as a full distribution. [GraalVM JDK 21 notes](https://www.graalvm.org/release-notes/JDK_21/) (VERIFIED). Note brucethemoose's README is older (recommends "EE 22.x", Java 17) — treat his EE claims as dated but directionally useful.
|
||
- Claims: client FPS gains are modest; chunk-gen/server workloads up to +20% on GraalVM EE. (DOCUMENTED-era 17: [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks).)
|
||
- Constraints: **must use G1 with his Graal flags; GraalVM (of his era) doesn't work with ZGC/Shenandoah** — and GraalVM 21 verifiably lacks GenZGC (see §3). (DOCUMENTED both.)
|
||
- Compatibility risk is real on 1.21.1: a dedicated fix repo exists because "Integrated Scripting 1.0.22" crashes on GraalVM JDK 21 + NeoForge 1.21.1 [jan-guenter/integratedscripting-graalfix](https://github.com/jan-guenter/integratedscripting-graalfix); players report packs failing on GraalVM Java 21 [r/feedthebeast](https://www.reddit.com/r/feedthebeast/comments/18hta1r/how_i_about_doubled_my_minecraft_performance/) (COMMUNITY). With Flywheel 1.0.6 + Veil/Lodestone + Sable/Aeronautics JIT-heavy stacks in this pack, GraalVM is a **trial**, never the fleet baseline. (INFERENCE.)
|
||
- Obydux's "Minecraft-GraalVM-Flags" is **server startup** flags for GraalVM EE Java 17 — not applicable to a 1.21.1 client; dropped. [Obydux repo](https://github.com/Obydux/Minecraft-GraalVM-Flags).
|
||
|
||
### 8. Prism Launcher settings (applies to P0 flatpak and P2)
|
||
- **Memory**: per-instance Settings → Java → memory box (Xms/Xmx). Prism warns against over-allocation (see §5). [Java settings wiki](https://prismlauncher.org/wiki/help-pages/java-settings/) (DOCUMENTED).
|
||
- **Java path / JVM args**: same Java page — set the Temurin/GraalVM `bin/java` path and paste JVM arguments. (DOCUMENTED: same page.)
|
||
- **Wrapper command**: "Wrapper command allows launching using an extra wrapper program (like 'optirun' on Linux)" — this is where `gamemoderun` goes (Settings → Custom Commands). [Custom commands wiki](https://prismlauncher.org/wiki/help-pages/custom-commands/) (DOCUMENTED).
|
||
- **Environment variables**: Prism passes env vars to the java runtime (instance-level). [Env vars wiki](https://prismlauncher.org/wiki/help-pages/environment-variables/) (DOCUMENTED). Use for `mesa_glthread=true`, `__GL_THREADED_OPTIMIZATIONS=0`, `vblank_mode=0` etc.
|
||
- Flatpak Prism on the Deck: official install is via their own flatpak repo [Prism Steam Deck download](https://prismlauncher.org/download/steam-deck/); gamemode from inside a flatpak goes through the xdg-desktop-portal GameMode interface (proxies to Feral's daemon with PID mapping/permission checks) [portal docs](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.GameMode.html); some flatpaks need `flatpak override --talk-name=com.feralinteractive.GameMode` for direct D-Bus access [example](https://github.com/an-anime-team/flatpak-builds) (DOCUMENTED + COMMUNITY).
|
||
|
||
### 9. Linux driver/OS levers
|
||
- **mesa_glthread**: moves GL dispatch to a second thread inside Mesa. radeonsi (which is what Minecraft's OpenGL actually uses on the Deck's Van Gogh APU — RADV is Vulkan and irrelevant here) enables glthread **by default since Mesa 22.3**; Mesa has also shipped a driconf default for the *official Minecraft launcher* app since 22.0 — a Prism-launched `java` process should not be assumed to match those overrides, so set `mesa_glthread=true` explicitly. [Phoronix](https://www.phoronix.com/news/Mesa-22.3-RadeonSI-glthread-On), [PCGamingWiki](https://www.pcgamingwiki.com/wiki/Mesa), [MangoHud issue #676](https://github.com/flightlessmango/MangoHud/issues/676) (VERIFIED driver behavior; explicit-set recommendation INFERENCE). Glthread is "a big help to CPU-bound games" — i.e., exactly the Deck's 4-core Zen2 profile. (Phoronix, VERIFIED quote.)
|
||
- **NVIDIA proprietary**: Sodium 0.8.x/0.6.x **sets `__GL_THREADED_OPTIMIZATIONS=0` itself** on Linux right before GLFW window creation (`Libc.setEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", "0")` in `NvidiaWorkarounds`), because threaded optimization causes stalls with Sodium. [NvidiaWorkarounds.java (1.21.1/stable)](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java) (VERIFIED). Setting it also in Prism env vars is harmless belt-and-braces.
|
||
- **gamemode**: `gamemoderun` as Prism wrapper; requests CPU governor + GPU perf level. [Feral GameMode](https://github.com/FeralInteractive/gamemode) / Prism wiki (DOCUMENTED, see §8).
|
||
- Optional: run java at raised priority (`renice` post-launch; negative nice needs root) — brucethemoose. (DOCUMENTED: README.)
|
||
|
||
### 10. Windows (P1) NVIDIA control panel
|
||
- **Threaded optimization is effectively not user-controllable for Minecraft**: Sodium's author (jellysquid3): the NVIDIA driver "forcefully enables Threaded Optimizations regardless of the control panel settings" because it hardcodes Minecraft detection for all `javaw.exe` processes. [sodium#2061](https://github.com/CaffeineMC/sodium/issues/2061) (VERIFIED, maintainer statement).
|
||
- What Sodium does on Windows instead: spoofs the process command line to `net.caffeinemc.sodium / net.minecraft.client.main.Main /` (keeps the driver's "good" Minecraft heuristics), then enables `GL_DEBUG_OUTPUT_SYNCHRONOUS` (KHR_debug) at context creation, which forces the driver to disable threaded command submission. It also detects the broken driver range x.y.15.2647–3622 (526.47 → before 536.23). [NvidiaWorkarounds.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java), [sodium#1486 referenced in source](https://github.com/CaffeineMC/sodium/issues/1486) (VERIFIED).
|
||
- NVCP **Power management mode → Prefer maximum performance** remains a legitimate per-app setting for stabilizing clocks; community standard advice for MC. [Minecraft Forum thread on threaded optimization/NVCP](https://www.minecraftforum.net/forums/minecraft-java-edition/discussion/3144703-nvidia-threaded-optimization), [r/feedthebeast NVCP report](https://www.reddit.com/r/feedthebeast/comments/vzkoc0/great_performance_improvement_using_nvidia/) (COMMUNITY). Note P1 is VRAM-bound (1060 6GB): platform levers help pacing, not the VRAM wall (INFERENCE).
|
||
|
||
### 11. Steam Deck (P0) specifics
|
||
- Install Prism via its official flatpak repo; add Prism (or `flatpak run org.prismlauncher.PrismLauncher --launch <Instance>` desktop entry) as a non-Steam-game so it launches in Game Mode under gamescope (SteamOS's compositor — no extra gamescope config needed at 1280×800 native). [Prism Steam Deck page](https://prismlauncher.org/download/steam-deck/), [RetroDECK wiki example with `--launch`](https://retrodeck.readthedocs.io/en/latest/wiki_experiments/desktop-launch/desktop-launch-prism/), [GamingOnLinux guide](https://www.gamingonlinux.com/2022/10/minecraft-on-steam-deck-guide-with-prism-launcher-and-gamepad-support/) (DOCUMENTED + COMMUNITY).
|
||
- **UMA frame buffer (VRAM) is 1 GB reserved by default**; BIOS allows 4 GB. With DH + shaderpacks + 212 mods on an 8CU iGPU, raising it to 4 GB is a common stability/smoothness tweak (2560×1600 shared-memory reads dominate on Deck). [Windows Central how-to](https://www.windowscentral.com/gaming/pc-gaming/how-to-increase-vram-on-steam-deck), [PiMyLifeUp](https://pimylifeup.com/steam-deck-increase-vram/) (COMMUNITY).
|
||
- TDP cap (e.g., 8–10 W) stabilizes clocks → steadier frame pacing on battery; standard Deck practice. (COMMUNITY.)
|
||
- GC choice on 4C/8T Zen2 with 16 GB *shared* RAM: tuned G1 or Shenandoah; avoid ZGC (concurrent-cycle CPU tax + heap headroom taken from the iGPU's shared pool). (INFERENCE from §2–§5.)
|
||
|
||
### 12. Sodium's "NO_ERROR_CONTEXT" workaround — what it actually means
|
||
- Sodium's options include **"Use No-Error Context"** (`sodium.options.use_no_error_context`, tooltip: "Creates the OpenGL context without error checking") — i.e., Sodium requests a `KHR_no_error` GL context by default to shave per-call driver error-checking overhead. (VERIFIED from Sodium's own lang strings: [sodium#3407](https://github.com/CaffeineMC/sodium/issues/3407).)
|
||
- When the installed driver can't provide that, Sodium logs `Sodium has applied one or more workarounds …: [NVIDIA_THREADED_OPTIMIZATIONS_BROKEN, NO_ERROR_CONTEXT_UNSUPPORTED]` — `NO_ERROR_CONTEXT_UNSUPPORTED` simply means the no-error-context optimization was **disabled** and a normal error-checking context is used; "not necessarily an issue, but it may result in certain features or optimizations being disabled." [sodium#2961 log excerpt](https://github.com/CaffeineMC/sodium/issues/2961) (VERIFIED).
|
||
- User-facing takeaway: don't try to "fix" this warning; it's informational. Performance impact on supported drivers is small. (INFERENCE.)
|
||
|
||
---
|
||
|
||
## Lever table (recommended value per fleet machine)
|
||
|
||
| Lever | Recommended value | P0 Deck (Zen2/16GB shared) | P1 Win i7-7700K/1060 6GB | P2 Linux i7-6700K/1080 Ti, 8GB free | Expected impact | Risk | Confidence |
|
||
|---|---|---|---|---|---|---|---|
|
||
| GC engine | P0/P2: Shenandoah (`-XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGuaranteedGCInterval=1000000`) or tuned G1; P1: Generational ZGC (`-XX:+UseZGC -XX:+ZGenerational`) | tuned G1 or Shenandoah | GenZGC (32 GB RAM makes headroom free) | tuned G1 or Shenandoah (not ZGC: RAM+CPU poor fit) | **High** (removes DH-flagged G1 stutters) | Low (config-only) | Med-High |
|
||
| G1 tuning (if G1) | brucethemoose client set: `MaxGCPauseMillis=37, G1NewSizePercent=23, G1HeapRegionSize=16M, G1MixedGCCountTarget=3, G1HeapWastePercent=20, IHOP=10, MaxTenuringThreshold=1` | yes | fallback if GenZGC regresses | yes | **Med** (1% lows) | Low | Med |
|
||
| Heap size | P0: 5–6 GB · P1: 6–8 GB · P2: 5 GB (Xmx=Xms except P2 low-RAM) | 5–6 GB | 6–8 GB | 5 GB, Xms<Xmx | **High** on P0/P2 (OOM/stutter), Med on P1 | Low | Med-High |
|
||
| `-XX:+AlwaysPreTouch` | on with Xms=Xmx | optional (slower boot from eMMC) | yes | skip (RAM-tight) | Low-Med (pacing consistency) | Low | Med |
|
||
| THP | `-XX:+UseLargePages -XX:+UseTransparentHugePages` with THP=`madvise` in sysfs (ZGC also needs `shmem_enabled=advise`) | test only | n/a (Windows: large pages need admin — skip) | test only (watch RSS bloat) | Low-Med | Low-Med | Low-Med |
|
||
| JVM distro | Temurin 21 baseline; GraalVM CE 21 as P1/P2 experiment (G1 only — no GenZGC on GraalVM 21) | Temurin | Temurin → GraalVM trial | Temurin → GraalVM trial (biggest CPU upside here) | Low-Med (Med upside on P2 CPU-bound scenes) | **Med** (mod miscompiles; e.g. Integrated Scripting fix repo) | Med |
|
||
| Prism wrapper | `gamemoderun` in Custom Commands → wrapper | yes | n/a | yes | Low-Med | Low | High (mechanism), Med (gain) |
|
||
| Prism env vars | `mesa_glthread=true` (P0); `__GL_THREADED_OPTIMIZATIONS=0` (P2) | yes | n/a | yes (Sodium also sets it; harmless) | Low-Med (P0 CPU-bound GL) | Low | Med-High |
|
||
| Mesa driver note | MC on Deck uses **radeonsi** (GL), not RADV; glthread default-on since Mesa 22.3 — still set env var for java | informational | n/a | n/a (NVIDIA proprietary has own path) | — | — | High |
|
||
| Windows NVCP | Power management: Prefer maximum performance; leave Threaded Optimization alone (driver ignores it for MC; Sodium's GL_DEBUG_OUTPUT_SYNCHRONOUS handles it) | n/a | yes | n/a | Low (P1 is VRAM-bound) | Low | Med |
|
||
| Steam Deck BIOS | UMA frame buffer 1 GB → 4 GB; cap TDP ~8–10 W | yes | n/a | n/a | Low-Med (stutter/stability) | Low-Med (BIOS fiddling) | Low-Med |
|
||
| Sodium no-error context | leave "Use No-Error Context" enabled; ignore `NO_ERROR_CONTEXT_UNSUPPORTED` log line | leave | leave | leave | ~0 (informational) | none | High |
|
||
|
||
---
|
||
|
||
## Sources
|
||
**Kept**
|
||
- [brucethemoose/Minecraft-Performance-Flags-Benchmarks README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) — the benchmarked flags reference (G1 client vs ZGC vs Shenandoah, memory oversizing, large pages, GraalVM caveats).
|
||
- [OpenJDK ZGC wiki](https://wiki.openjdk.org/display/zgc/Main) — authoritative GenZGC flags, heap-headroom rule, SoftMaxHeapSize, AlwaysPreTouch, THP prerequisites.
|
||
- [JEP 474](https://openjdk.org/jeps/474) + ZGC wiki changelog — ZGenerational default only on JDK 23; non-gen removed JDK 24.
|
||
- [GraalVM for JDK 21 release notes](https://www.graalvm.org/release-notes/JDK_21/) — CE/Oracle split; Generational ZGC not available on GraalVM 21.
|
||
- Sodium source, branch [1.21.1/stable](https://github.com/CaffeineMC/sodium/tree/1.21.1/stable): [NvidiaWorkarounds.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java), [AmdWorkarounds.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/amd/AmdWorkarounds.java), [WindowMixin.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java), [sodium#2061](https://github.com/CaffeineMC/sodium/issues/2061), [sodium#2961](https://github.com/CaffeineMC/sodium/issues/2961), [sodium#3407 (lang strings)](https://github.com/CaffeineMC/sodium/issues/3407) — exact meaning of NO_ERROR_CONTEXT / NVIDIA threaded-optimization workarounds, incl. `__GL_THREADED_OPTIMIZATIONS=0` on Linux.
|
||
- [Sodium Modrinth versions for 1.21.1 NeoForge](https://modrinth.com/mod/sodium/versions?g=1.21.1&l=neoforge) — confirms pack's Sodium 0.8.13 backport, Iris 1.8.13 / Sable / Aeronautics compat notes.
|
||
- [Prism wiki: Java settings](https://prismlauncher.org/wiki/help-pages/java-settings/), [Custom commands](https://prismlauncher.org/wiki/help-pages/custom-commands/), [Environment variables](https://prismlauncher.org/wiki/help-pages/environment-variables/), [Steam Deck download](https://prismlauncher.org/download/steam-deck/) — memory/java path/wrapper/env-var surfaces; flatpak install.
|
||
- [Phoronix: Mesa 22.3 RadeonSI glthread default](https://www.phoronix.com/news/Mesa-22.3-RadeonSI-glthread-On) + [PCGamingWiki Mesa](https://www.pcgamingwiki.com/wiki/Mesa) + [MangoHud#676](https://github.com/flightlessmango/MangoHud/issues/676) — glthread semantics/defaults and the Minecraft-launcher driconf nuance.
|
||
- DH warning text corroborated: [Minecraft Forum log](https://www.minecraftforum.net/forums/support/java-edition-support/3228579-modpack-randomly-losing-fps-and-sometimes-crashing), [New Eden on Modrinth](https://modrinth.com/project/7jwudrLZ).
|
||
- [Red Hat Temurin docs](https://docs.redhat.com/en/documentation/red_hat_build_of_openjdk/21/html-single/getting_started_with_eclipse_temurin/index) — Shenandoah bundled from 11 onward.
|
||
- [jan-guenter/integratedscripting-graalfix](https://github.com/jan-guenter/integratedscripting-graalfix) — concrete GraalVM JDK 21 + NeoForge 1.21.1 incompatibility.
|
||
- [Windows Central UMA frame buffer](https://www.windowscentral.com/gaming/pc-gaming/how-to-increase-vram-on-steam-deck) — Deck VRAM default/BIOS option.
|
||
- [xdg-desktop-portal GameMode](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.GameMode.html) — gamemode from inside flatpaks.
|
||
|
||
**Dropped**
|
||
- [Obydux/Minecraft-GraalVM-Flags](https://github.com/Obydux/Minecraft-GraalVM-Flags) — server startup flags, GraalVM EE Java 17 era; wrong target (client, Java 21).
|
||
- [fumora.net GraalVM vs OpenJDK "benchmarks"](https://www.fumora.net/lab/minecraft-graalvm-vs-openjdk) — third-party, server-plugin workload, methodology unclear.
|
||
- DriverEasy/SystWeak "fix stutter" pages — SEO content, low value.
|
||
- Most Reddit threads kept only as corroboration, not as primary claims (DH warning wording, GraalVM pack failures).
|
||
|
||
## Gaps
|
||
- **No credible client-side G1-vs-GenZGC-vs-Shenandoah benchmark for 200+ mod NeoForge 1.21.1 with DH** was found; brucethemoose's data is 1.20-era Java 17 and DH's warning is the only pack-specific signal. Must A/B locally (see below).
|
||
- Whether Shenandoah is present in *current Temurin 21 Windows x64* builds was not definitively confirmed (Red Hat doc implies yes; some historic Temurin builds lacked it) — verify with `java -XX:+UseShenandoahGC -version` per machine.
|
||
- SteamOS 3.x current THP sysfs defaults (`transparent_hugepage/enabled`, `shmem_enabled`) not verified remotely — check on device.
|
||
- Whether any mod in this pack (AllTheLeaks 1.1.13, DH 3.3.2) calls `System.gc()` such that `-XX:+DisableExplicitGC` would be counterproductive — not verified.
|
||
- Sodium 0.8.13-for-1.21.1 is a 2026 backport; exact workaround-list parity with mainline 0.8.x assumed (INFERENCE from 0.8.12 changelog "Improvements for hardware and mod compatibility").
|
||
|
||
## Top levers (ranked)
|
||
1. **Move off stock G1 per DH's warning** — P1: Generational ZGC; P0/P2: Shenandoah or client-tuned G1. Expected impact **High** (1% lows / hitching with DH LOD streams). All machines. Risk: low (launcher config). Confidence: Med-High.
|
||
2. **Heap sizing discipline** (P0 5–6 GB, P1 6–8 GB, P2 5 GB; Xms=Xmx except P2). Impact **High** on P0/P2, Med on P1. Risk low. Confidence Med-High.
|
||
3. **`mesa_glthread=true` + `gamemoderun` on the Deck** (explicit env var; glthread default-on only for driver/launcher overrides, not necessarily java). Impact **Med** (CPU-bound GL dispatch on 4 cores). Risk low. Confidence Med.
|
||
4. **GraalVM CE 21 trial on P2 (and P1)** — G1-only, keep Temurin fallback. Impact **Med** (CPU-bound chunk/scene prep). Risk **Med** (miscompiles; no GenZGC). Confidence Med.
|
||
5. **`__GL_THREADED_OPTIMIZATIONS=0` env var on P2** (Sodium already sets it — belt-and-braces). Impact **Low-Med**. Risk none. Confidence High (mechanism), Med (gain).
|
||
6. **AlwaysPreTouch (+THP `madvise`) with Xms=Xmx on P1; test on P0; skip on P2**. Impact Low-Med (pacing consistency, slower boot). Risk low-med. Confidence Med.
|
||
7. **Deck BIOS UMA 4 GB + TDP cap ~8–10 W**. Impact Low-Med (stability/frame pacing with DH+shaders on 8CU). Risk low-med. Confidence Low-Med.
|
||
8. **Windows NVCP "Prefer maximum performance" on P1; leave Threaded Optimization untouched** (Sodium overrides it in code). Impact Low (VRAM-bound). Risk none. Confidence Med.
|
||
|
||
## Open questions to verify by benchmark
|
||
1. On each machine: G1 client-tuned vs Shenandoah vs GenZGC — 1% lows, 0.1% lows and hitch count during DH LOD streaming + chunk gen (use Spark GC monitor + Sodium 0.8.x FPS percentiles).
|
||
2. P1: does GenZGC at 6–8 GB show longer average frame times (concurrent CPU tax) than tuned G1 on the 7700K?
|
||
3. P2: at 5 GB heap with server view-distance 8 + DH, does live-set actually fit (Spark `gcmonitor` / allocation-rate), or is Shenandoah/G1 forced to over-collect?
|
||
4. Does `-XX:+DisableExplicitGC` change behavior of DH 3.3.2 / AllTheLeaks 1.1.13 in this pack (explicit-GC dependence)?
|
||
5. GraalVM CE 21: does the full pack (Flywheel 1.0.6, Veil/Lodestone, Sable 2.0.5, Aeronautics 1.3.2, SSRD) survive a 30-min play session without miscompile crashes, and net FPS on P2?
|
||
6. Deck: `mesa_glthread=true` on/off — measure avg FPS and 1% lows at 1280×800 with Complementary Reimagined r5.9.3 vs MakeUp Ultra Fast 9.5f; also confirm current SteamOS Mesa version's glthread default for a Prism-launched java process.
|
||
7. Deck: UMA 1 GB → 4 GB — measurable reduction in texture-streaming hitches with DH + shaders?
|
||
8. THP `madvise` on P2 (and `shmem_enabled` if ZGC tested): THP on/off delta on frame pacing and RSS.
|
||
9. Windows P1: with Sodium active (GL_DEBUG_OUTPUT_SYNCHRONOUS path), any measurable difference from NVCP Threaded Optimization settings at all? (Expect none — confirm.)
|
||
10. Xms=Xmx + AlwaysPreTouch on the Deck: startup time penalty vs frame-pacing benefit.
|