Skip to content

Measurements: --state-in-memory beats the C backend on every title and platform tested; without it the LLVM backend loses to C #29

Description

@dougchansan

Not a bug report — a measurement writeup, since --state-in-memory is opt-in and off by default and the numbers suggest that default is worth revisiting.

Everything below uses code already in main; nothing here needs a patch.

Result

Control is the C backend. Arms are LLVM variants from the same recompiler binary against the same DOL; only backend and state mode differ. Ratios are arm/control, so >1.0 is faster than C.

title --backend llvm --backend llvm --state-in-memory scenes
Luigi's Mansion (GLME01) 1.185 1.472 2
Skyward Sword (SOUE01) 0.896 1.194 2
Mario Kart: Double Dash (GM4E01) 0.906 1.145 3
Pokémon Colosseum (GC6E01) 0.827 1.040 8

Two things stand out:

  1. Without --state-in-memory, the LLVM backend is slower than C on three of the four titles (0.83–0.91).
  2. With it, LLVM beats C on all four. The swing on Colosseum is 0.827 → 1.040 across 8 independent scenes.

Colosseum's figure is the most sampled: 8 scenes spanning 12.8–37.2 fps, and the llvm arm landed in 0.773–0.876 on every one of them.

Method

  • runtime is ModernGekko with the static-recomp core; frames advanced in a fixed window, uncapped
  • each scene is a savestate; interleaved forward and reversed control/arm pairs, medians compared
  • host input pinned (no device bound, BackgroundInput = False) and one emulator at a time — both mattered, see below
  • Colosseum's MSR region-leader fix (Make the instruction after an MSR write a region leader #28) is present in all arms, so it is not what is being measured here

Noise floor was measured, not assumed

The same C module was supplied as both control and arm, so the true ratio is exactly 1.0000:

n=13 null comparisons across 4 titles / 6 scenes
12 of 13 within +/-1.72%
 1 of 13 at +14.97%  (one scene; 3 repeats of it then returned 1.0164 / 0.9972 / 1.0019)

Single runs therefore carry a rare ~15% excursion. Every number above is a mean over repeated runs. Several earlier single-run figures in this work did not survive repetition and were discarded.

Caveats worth stating

  • x86-64 Windows only. No aarch64 or macOS numbers yet, and state-in-memory could plausibly behave differently where register pressure differs.
  • Scene counts are uneven (8 for Colosseum, 2–3 elsewhere).
  • Savestate hygiene matters more than expected: of 38 Colosseum states available here, 17 carried a widescreen patch in their RAM image and reported SMC: chunk [0x80005300,0x80005500) hash mismatch. They boot and render normally while that chunk silently falls back to the interpreter. Anyone reproducing this should check the runtime log for hash mismatch and confirm frame_count actually advances.

Why post it

--state-in-memory currently reads as an experimental toggle. On this hardware and these titles it is the difference between the LLVM backend being a regression against C and being a win. If that reproduces elsewhere, the default may be worth changing — and if it does not reproduce on other targets, that is worth knowing too.

Happy to run additional titles or scenes if useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions