https://bugs.winehq.org/show_bug.cgi?id=48408
--- Comment #4 from florian.will@gmail.com --- Created attachment 66231 --> https://bugs.winehq.org/attachment.cgi?id=66231 grepped dsound trace log with freezes at 48531-48541 and 48578-48591
I agree it's difficult to come up with a solution that doesn't sacrifice mixing performance. In a related issue, #30639, Erich E. Hoover shared his plans in comment #44 to move the actual mixing code (or parts of it) out of the buffer_list_lock. I have looked at it and can't find a way to do this without copying the secondary buffers to a new memory location first, because the buffers can be freed / realloced while working on them if the lock is not held.
I use a special Zusi 3 "six long freight trains in one place" test scenario. It was created to hunt down performance issues on Windows related to that situation, so I guess there might be a similar issue even on Windows (although current consensus appears to be that it's related to freight train animations, but sound has been mentioned in that context). While that test scenario is artificial, similar situations exist in "real" Zusi 3 scenarios at major freight yards and the freezes and/or sound stuttering in wine are quite common there in my experience. (mixer performance seems to be better in Windows for me, I have not encountered the sound stuttering there. I will test the test scenario using Windows when I find some time to boot it, to see if it causes stuttering and/or freezes.)
That said, in the test scenario, I get up to 381 secondary sound buffers. I have a full dsound trace log while using your SRW patch, but it's 340 MB. I guess the interesting part is grep "AddBuffer|RemoveBuffer", so I'm attaching that. Let me know if you want more log parts or the full log. Major freezes happen between timestamps 48531-48541 (first freeze) and 48578-48591 (second freeze).
The logs show that RemoveBuffer sometimes needs to wait 60ms or more to acquire the lock (first line like "(019A17A0, 18FBDBD0)" is start of function execution, second line with buffer count is end of function). With the Sleep(1)s added, it manages to do 5-10 AddBuffer calls before another PerformMix() round starts in the mixthread and the >60ms delay kicks in.
Note that I'm always using Proton 4.11-11 for these tests in the real game (not sure how to convince the Steam DRM to launch the game in upstream wine), and not using a clean wine prefix (the game requires some winetricks). I just copy over my dllsound.dll.so and .fake to Protons dist/lib/wine dir and remove Proton's dsound.dll.
I'd say your patch fixes this bug report. Game freezes that last forever (or many minutes) are replaced with relatively short freezes. If a fix for #30639 can be found, like the "fast mixer" patch from wine-staging, experience should be quite good in most scenarios, and maybe similar to Windows. According to my reproducer, my 10 year old CPU (Phenom II X4 955) can handle ~250 secondary buffers using the fast wine-staging mixer. So the possible short freezes would be limited to areas with lots of freight trains then. Using the current "not so fast, but higher quality" mixer, which only supports up to ~90 sound buffers for me, sometimes 1 freight train is enough to cause some sound issues and lags.