Re:Stride – Open-source C# Game Engine
by kevingadd on Sunday February 05, 2023 @01:13PM
(#34667202)
This is a great strategy as long as you can keep the pause times low enough - especially if you manage to hide the gc behind vertical sync. Getting the exact timing for that is a little tricky, but if your game is running fast enough you've probably got upwards of 5ms waiting to be used while your main thread blocks inside Present/SwapBuffers. (Because those functions are native OS APIs, there won't be managed code on the stack and the GC should be able to run.)
Re:Stride – Open-source C# Game Engine
by starburst on Sunday February 05, 2023 @02:29PM
(#34668171)
This is NOT a great strategy, although better than waiting for the 100-1000ms collection you're still at the mercy of the GC which can be very random and you will miss some VSync for sure doing that even if you're supposed to have some "room".
Missing a VSync in mobile means that the refresh rate will switch to 30hz for a brief moment, there is no in-between (ie; 54 FPS or something like that) which is pretty noticeable.
The only "great strategy" is to have zero alloc (or close) while gameplay is running and if you want to go the extra miles, disable GC completely and call it only in some appropriate moment (level loading, bringing up the menu, etc.).
> The only "great strategy" is to have zero alloc (or close)
This is the path I am taking.
Ultimately, I would try as hard as I can to not allocate, but having a good plan for dealing with some per-frame blips is going to be essential. It gives me a reasonable starting point to work with on the journey to zero alloc.
I have a prototype where I intentionally invoke GC after every frame. My reasoning is that some amount of GC will eventually need to occur, so why not do it as frequently as possible and at the exact moment where we can compensate with other measures, such as the frame scheduler & time step abstractions.
Even with heavy allocation (i.e. deserializing the scene graph from a wire protocol before every frame), this approach seems to keep GC pauses bounded to ~1-5 milliseconds in my implementations.
If I did not explicitly call GC when I thought best, the runtime would decide to run a 100-1000 ms collection at its convenience and the entire experience would become worthless to human perception.