I would suggest to disable TieredCompilation in your csproj, always (as well as Ready2Run, but that doesn’t affect debugging). But I don’t think this would have any impact on your small example (the IL code would likely be entirely JIT’d).
In your test solution, all of your WriteLine() generate garbage because of the string constructions (this is what makes the memory usage to grow). In a small example like this one it’s not dramatic, but if you have that throughout all your code base, it will very much likely trigger garbage collections at some point.
One thing that might cause stutter is the GPU driver, especially when it enforces Vsync despite whatever you set from MonoGame (and intel drivers for OpenGL are notoriously meh). It might cause desyncs between the FixedTimeStep and the GPU driver, hence visible hiccups.
Also, there is a MonoGame behavior which might lead to misinterpretation: if the application isn’t focused, the game loop sleeps every frame to consume less power. It will sleep for InactiveSleepTime
(which by default is much lower than 60fps). You can disable that by setting InactiveSleepTime
to 0.
To make proper performance test, I would suggest disabling IsFixedTimeStep
and enabling _graphics.SynchronizeWithVerticalRetrace
. If you have stutters from here, it’s most definitely the code generating GC’s or .NET JIT’ing stuff.
On another topic, if you disable both Vsync and fixed timestep, an empty project will run so fast that the frame pacer accuracy will be outmatched, possibly generating misleading stutters. But in your example you are drawing some sprites, so I would assume that the frame pacer is able to do its job (unless you friend’s and your machine are overpowered).
In regard to not having issues with XNA back in the days, it turns out the .NET runtime has also evolved a lot and they changed much of it to be more performant, which also made it much more picky in regard to the code you write. I’m not saying that it’s necessarily your code, it could also be MG’s frame pacer having issues, so just some insights.
MonoGame itself is designed to generate 0 garbage past LoadContent(). So if the problem really is the GC, I would look into writing garbage free code with C# (I might do a write up about that at some point).