MacGamingFixes
macgamingfixes / registry save deferral

registry save deferral

part of macgamingfixes. the same article is in the app, next to the switch.

wine freezes every process in a bottle for about a quarter of a second, twice a minute, to rewrite its registry. this fix holds that write back while a game is running.

symptom

every 30 s the game hitches. the network graph shows 15–17 ticks arriving in one burst. it happens on loopback too, so wi-fi is not involved.

cause

wineserver is single-threaded. every 30 s it rewrites each registry branch that changed since the last save, as one text file, on that one thread. in a steam bottle system.reg is about 12 mb (36.5k keys), so one save blocks every server call and socket event for ~240 ms.

the branch is never clean for long: steam touches HKLM\Software\Wow6432Node\Valve\SteamService once a minute.

measurement

a 64 hz udp echo on loopback, received inside the game bottle the way valve's networking code receives (WSAEventSelect + recvfrom). deadlock running, 110–120 s per run.

receiverp99maxlate > 5 ms
native1.2 ms8 ms2 / 7040
wine, stock6.1 ms264 ms80 / 7040
wine, fixed3.1 ms10 ms18 / 7680
longest stallbefore264 msafter10 ms

the four stock stalls were 232–264 ms long, exactly 30 s apart, and each ended within 7 ms of system.reg being rewritten.

the fix

a small library is injected into wineserver and interposes open(). when the periodic save of a branch larger than 1 mb begins while the server is busy (its own cpu share above 5 %), the temp-file open fails fast. the branch stays dirty, wineserver retries 30 s later, and the save goes through once the bottle is quiet. saves on exit and of small branches such as user.reg are untouched.

wineserver_fix.c
if (branch[0] && periodic) {
    double share = cpu_share();
    if (busy_cpu > 0 && share > busy_cpu) {  // a game is running
        errno = EACCES;                      // save_branch() gives up, branch stays dirty
        return -1;
    }
}
return open(path, flags, mode);

what changes on disk

verify

play for a few minutes, then read the log. a game session shows one defer system.reg line every 30 s.

tail -f ~/Library/Logs/mgf/regsave.log

limits