I made a couple minor fixes to the class, to fix a math error which seemed to be due to a bug, that i left in from a larger test project. I just re-posted the 3 class files instead of the whole project.
FrameRate class is a bit over complicated at a glance to see how you've built the strings
Well i really did it like that so you could change the bool in the example and see the difference between a regular string builders output and this versions but i maybe put to many examples in there.
I couldnt figure out if there was a better way to format the string the way I wanted it to display but this did the trick.
They way you did it or some other inventive manner of doing that. Is probably required for formatting numerical things to a specific manner of display, If one wants to not create garbage.
The AppendTrim function itself limits the decimal places to 3 that's about all the custom formatting i added. Which was just done as a example to show how you could alter the outputted text mathematically, by simply breaking the while loop after a specific number of iterations.
I suppose since this is somewhat of a hack around the root of the problem which unfortunately is in dot net. Its pretty much create your own formatting at least for numerical display
Can you explain how this one works different to the default stringbuilder
This basically wraps a StringBuilder and intercepts the numerical calls and does them instead that's about the jist of it, well there is a little more.
It additionally keeps a couple extra static swaping string builders around in case a big capacity change occurs in one of them so it doesn't cause garbage to escape in that manner. The operators allow you to use it with a regular StringBuilder or swap one into or out of it if need be or for convenience.
and why it's preferable?
I tried quite a few different peoples solutions, some that dug very deep. All of them show the same problem, most all of them missed the root cause. Which was that numbers being converted to strings even with stringbuilder, simply create temporary garbage no matter what.
That garbage can and will be marked and swept by the gc when enough garbage that is markable builds up. It then at some point causes a GC collection to occur that for the user this appears as a stutter in a game, which it is.
Your entire app must wait for the GC to finish taking out the trash. While not a big deal for say a calculator on your desktop. For a game going at 60fps or more its very noticeable.
For the game programmer it makes it hard to differentiate in real time at a glance when something else that he is doing creates a GC problem when your very informational numerical displayed output is also causing collections.
To think of it simply, its like a temporary object going out of scope, each time you turn a number into a character via c#.
Even though it is said that char and numerics are primitive value types when it comes to conversion. We can see in the framerate test given (by switching on the regular stringbuilder and running with no fixed timestep ) that this is not what you see what you see is garbage and collections.
Some where deep down below StringBuilder and String, a temp character object is created and forgotten for each numerical value changed to a character. This is c# wide not limited to monogame.
The reason this works is we never actually ask for a conversion at all, we mathematically calculate the numerical character ourselves and only allow a character to be created. Until we let our stringbuilder go out of scope or call new on it. We wont be allowing the gc to mark it for sweeping.
Unfortunately StringBuilder and Strings, underlying ToString conversion itself, needs to actually be re-written internally within dot net, for a proper fix to the problem. Because this does work im like 90% sure this is actually a unrealized bug within .net.
I spent a good amount of time attempting to make this class have all the functionality of a regular string e.g. MyStringBuilder = "some variable" + 10.5 + newline; Which yielded unfavorable results.
While this was possible, it wasn't 'properly' possible due to the rules of operator overloading being a little to loose and not strict enough to allow it to work without generating garbage, and not really worth it even with a regular string builder, because of the extra stuff involved.