Collect and show perf sample totals in widget#22326
Conversation
| { | ||
| public class PerfGraphWidget : Widget | ||
| { | ||
| static string InnerFormatFloatWithoutPartial(double value, int digits) |
There was a problem hiding this comment.
this whole method seems a bit expensive and complicated just to be able to get a float on screen?
There was a problem hiding this comment.
It is a special 6 character format that excludes the one's place zero if a number < 0. I wanted to show as many useful digits while keeping the columns aligned or mostly aligned and have some room for longer sample names. Sadly, this was my attempt to make it readable. However, this is a reason to have fun writing a performant version as I have. The new version always appends 6 characters to the StringBuilder.
| return text.Length <= digits ? text + '.' : text; | ||
| } | ||
|
|
||
| public static string FormatFloat(double value, int digits = 5) |
There was a problem hiding this comment.
if this will be called at 60+ fps, please consider using caches text values that only update each second. or on a higher level.
| var maxExtraDotSpace = 0; | ||
| foreach (var item in PerfHistory.Items.Values) | ||
| maxExtraDotSpace = Math.Max(maxExtraDotSpace, Game.Renderer.Fonts["Tiny"].Measure(item.Name).X); | ||
| var dotWidth = Game.Renderer.Fonts["Tiny"].Measure(".").X; |
There was a problem hiding this comment.
measure is also horrible slow.
take it outside the loop at least.
There was a problem hiding this comment.
Widths are now cached in a Cache dictionary.
5cf14a5 to
141f238
Compare
|
Replace the public PerfGraphWidget()
{
textWidthCache = new(GetTextWidth);
dotWidth = textWidthCache["."];
nextDotAdvance = textWidthCache[".."] - dotWidth;
TestFormatFloat(double.NaN, "NaN ");
TestFormatFloat(-0.000001, "<0 ");
TestFormatFloat(0.000001, ".00000");
TestFormatFloat(0.000004, ".00000");
TestFormatFloat(0.000005, ".00001");
TestFormatFloat(0.000009, ".00001");
TestFormatFloat(0.00001, ".00001");
TestFormatFloat(0.00004, ".00004");
TestFormatFloat(0.00005, ".00005");
TestFormatFloat(0.00009, ".00009");
TestFormatFloat(0.0001, ".00010");
TestFormatFloat(0.0004, ".00040");
TestFormatFloat(0.0005, ".00050");
TestFormatFloat(0.0009, ".00090");
TestFormatFloat(0.001, ".00100");
TestFormatFloat(0.005, ".00500");
TestFormatFloat(0.01, ".01000");
TestFormatFloat(0.05, ".05000");
TestFormatFloat(0.1, ".10000");
TestFormatFloat(0.5, ".50000");
TestFormatFloat(1, "1.0000");
TestFormatFloat(9, "9.0000");
TestFormatFloat(10, "10.000");
TestFormatFloat(99, "99.000");
TestFormatFloat(100, "100.00");
TestFormatFloat(123.4321, "123.43");
TestFormatFloat(1000, "1000.0");
TestFormatFloat(10000, "10000.");
TestFormatFloat(100000, "100000");
TestFormatFloat(123432, "123432");
TestFormatFloat(1000000, "TooBig");
TestFormatFloat(1234321, "TooBig");
TestFormatFloat(10000000, "TooBig");
TestFormatFloat(100000000, "TooBig");
}
void TestFormatFloat(double value, string expected)
{
var builder = new StringBuilder();
SixCharacterFormatFloat(builder, value);
Console.WriteLine($"{(builder.Length == 6 && builder.ToString() == expected ? "PASS" : "FAIL")} {expected} : {builder} <= {value}");
} |
cd12e0f to
6ea2315
Compare
|
I made the formatter shorter with loops to reduce size, added comments and gave it a less confusing name. |
Both the rolling and cumulative active (not paused) means are shown.
6ea2315 to
f532e43
Compare
PunkPun
left a comment
There was a problem hiding this comment.
Seems a bit crazy to optimise rendering for just like 8 words that are only going to be rendered once a frame. Though if we are optimising, then there's still so many overheads left.
Could you also push the unit tests?
| } | ||
|
|
||
| public void Tick() | ||
| public void Tick(bool gameIsActive = true) |
There was a problem hiding this comment.
I'm not sure if this makes sense? The game can be paused but the render loop will still be running.
There was a problem hiding this comment.
I thought about that when I made this and there is still the rolling average. I figured that adding this so that the second column would consistently be the cumulative active means (averages).
7fe5ff6 to
1c176a5
Compare
|
I have added the unit tests, handled a rounding issue and added handling of infinities. |
Both the rolling and cumulative active (not paused) means are shown.
The cumulative active means (averages) can be used with repeated runs of (multiple) replays to collect performance data and compare. This does not help in the discovery of slow areas, but does allow anyone (who can run the game and collect numbers) to test performance differences (requiring the ability to checkout code and build for checking code changes in the repository).