From a873ae82509ec1e1259ffbd5d784d2d8dc4e2245 Mon Sep 17 00:00:00 2001 From: jpolo1224 Date: Mon, 10 Aug 2026 23:56:15 -0400 Subject: [PATCH] Settings: let idle SPUs sleep instead of spinning on a reservation SPU GETLLAR Busy Waiting Percentage defaults to 100 upstream, meaning always busy-wait. That suits a desktop, where the SPU threads have cores of their own and spinning costs nothing else. Here six of them share eight cores with the PPUs and the RSX, so a spinning SPU takes a core from the threads doing the work. Measured on Spider-Man: Web of Shadows: process_mfc_cmd accounted for 55% of all CPU across the process, and making its inner loop cheaper did not move the frame rate -- the loop just ran more iterations in the same wall clock. That is what identified it as a spin rather than as work, after two rounds of optimising the iteration itself. 20 still favours a short busy-wait, so a reservation that frees quickly is caught without a scheduler round trip, and only a wait that history says is long goes to sleep. A deliberate change in All Core Settings still wins, since core overrides replay after this. --- .../src/main/java/com/armsx2/config/Settings.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/android/armsx3-ui/app/src/main/java/com/armsx2/config/Settings.kt b/android/armsx3-ui/app/src/main/java/com/armsx2/config/Settings.kt index 4698c9936..9db781e16 100644 --- a/android/armsx3-ui/app/src/main/java/com/armsx2/config/Settings.kt +++ b/android/armsx3-ui/app/src/main/java/com/armsx2/config/Settings.kt @@ -1260,6 +1260,21 @@ data class Settings( // above it would already be 60; setting it explicitly means the cap does not depend // on the vblank path holding, which it did not. Enum node, so the value is quoted. runCatching { net.rpcsx.RPCSX.instance.settingsSet("Video@@Frame limit", "\"60\"") } + // Let idle SPUs sleep instead of spinning on a reservation. + // + // Upstream defaults this to 100, which means always busy-wait. That is right for a + // desktop, where six SPU threads have cores of their own and spinning costs nothing + // else. Here they share eight cores with the PPUs and the RSX, so a spinning SPU is + // taking a core away from the threads doing the work. + // + // Measured on Spider-Man: Web of Shadows: process_mfc_cmd was 55% of all CPU across + // the process, and making its inner loop cheaper did not move the frame rate at all -- + // the loop simply ran more iterations in the same wall clock, which is what identified + // it as a spin rather than as work. + // + // 20 still favours a short busy-wait, so a reservation that frees quickly is caught + // without a scheduler round trip; only a wait that history says is long goes to sleep. + runCatching { net.rpcsx.RPCSX.instance.settingsSet("Core@@SPU GETLLAR Busy Waiting Percentage", "20") } // Compatible Savestate Mode is no longer forced off here; applyTo writes it from // ps3.savestateCompatibleMode above, so the two costs it carries -- SPU performance // and a 500MB to 3GB state file -- are the user's to accept rather than a decision