Collect and show perf sample totals in widget
Both the rolling and cumulative active (not paused) means are shown.
This commit is contained in:
committed by
Gustas Kažukauskas
parent
ef5541cce4
commit
2516c5a798
@@ -661,7 +661,7 @@ namespace OpenRA
|
||||
|
||||
world.Tick();
|
||||
|
||||
PerfHistory.Tick();
|
||||
PerfHistory.Tick(!world.Paused);
|
||||
}
|
||||
|
||||
// Wait until we have done our first world Tick before TickRendering
|
||||
@@ -759,12 +759,13 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
PerfHistory.Items["render"].Tick();
|
||||
PerfHistory.Items["batches"].Tick();
|
||||
PerfHistory.Items["render_world"].Tick();
|
||||
PerfHistory.Items["render_widgets"].Tick();
|
||||
PerfHistory.Items["render_flip"].Tick();
|
||||
PerfHistory.Items["terrain_lighting"].Tick();
|
||||
var isActive = !(worldRenderer?.World.Paused ?? true);
|
||||
PerfHistory.Items["render"].Tick(isActive);
|
||||
PerfHistory.Items["batches"].Tick(isActive);
|
||||
PerfHistory.Items["render_world"].Tick(isActive);
|
||||
PerfHistory.Items["render_widgets"].Tick(isActive);
|
||||
PerfHistory.Items["render_flip"].Tick(isActive);
|
||||
PerfHistory.Items["terrain_lighting"].Tick(isActive);
|
||||
}
|
||||
|
||||
static void Loop()
|
||||
|
||||
@@ -41,11 +41,11 @@ namespace OpenRA.Support
|
||||
Items[item].Val += x;
|
||||
}
|
||||
|
||||
public static void Tick()
|
||||
public static void Tick(bool gameIsActive = true)
|
||||
{
|
||||
foreach (var item in Items.Values)
|
||||
if (item.HasNormalTick)
|
||||
item.Tick();
|
||||
item.Tick(gameIsActive);
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace OpenRA.Support
|
||||
public double Val = 0.0;
|
||||
int head = 1, tail = 0;
|
||||
public bool HasNormalTick = true;
|
||||
public double ActiveGameTotal { get; private set; } = 0.0;
|
||||
public int ActiveGameTotalSamples { get; private set; } = 0;
|
||||
|
||||
public PerfItem(string name, Color c)
|
||||
{
|
||||
@@ -29,9 +31,15 @@ namespace OpenRA.Support
|
||||
C = c;
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
public void Tick(bool gameIsActive = true)
|
||||
{
|
||||
samples[head++] = Val;
|
||||
if (gameIsActive)
|
||||
{
|
||||
ActiveGameTotal += Val;
|
||||
ActiveGameTotalSamples++;
|
||||
}
|
||||
|
||||
if (head == samples.Length) head = 0;
|
||||
if (head == tail && ++tail == samples.Length) tail = 0;
|
||||
Val = 0.0;
|
||||
@@ -63,6 +71,11 @@ namespace OpenRA.Support
|
||||
return i == 0 ? sum : sum / i;
|
||||
}
|
||||
|
||||
public double ActiveGameTotalAverage()
|
||||
{
|
||||
return ActiveGameTotal / ActiveGameTotalSamples;
|
||||
}
|
||||
|
||||
public double LastValue
|
||||
{
|
||||
get
|
||||
@@ -78,6 +91,8 @@ namespace OpenRA.Support
|
||||
head = 1;
|
||||
tail = 0;
|
||||
Val = 0.0;
|
||||
ActiveGameTotal = 0.0;
|
||||
ActiveGameTotalSamples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Widgets;
|
||||
@@ -18,6 +21,92 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
public class PerfGraphWidget : Widget
|
||||
{
|
||||
readonly int dotWidth;
|
||||
readonly int nextDotAdvance;
|
||||
readonly Cache<string, int> textWidthCache;
|
||||
readonly SpriteFont font = Game.Renderer.Fonts["Tiny"];
|
||||
StringBuilder builder = null;
|
||||
|
||||
public PerfGraphWidget()
|
||||
{
|
||||
textWidthCache = new(GetTextWidth);
|
||||
dotWidth = textWidthCache["."];
|
||||
nextDotAdvance = textWidthCache[".."] - dotWidth;
|
||||
}
|
||||
|
||||
int GetTextWidth(string text) => font.Measure(text).X;
|
||||
|
||||
public void SixCharacterFormatFloat(StringBuilder output, double value)
|
||||
{
|
||||
// Try to keep the text at 6 characters long to align columns.
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
output.Append("NaN ");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
output.Append("<0 ");
|
||||
return;
|
||||
}
|
||||
|
||||
value += 0.000005; // Do normal rounding instead of floor/trucate;
|
||||
var intValue = (int)value;
|
||||
if (intValue >= 1000000)
|
||||
{
|
||||
output.Append("TooBig");
|
||||
return;
|
||||
}
|
||||
|
||||
var partValue = (int)value;
|
||||
var digit = partValue / 1000000;
|
||||
if (intValue >= 1000000)
|
||||
output.Append((char)(digit + '0'));
|
||||
|
||||
// Append the whole part.
|
||||
for (var p = 1000000; p >= 10;)
|
||||
{
|
||||
var n = p / 10;
|
||||
|
||||
// Skip leading zeros.
|
||||
if (intValue >= n)
|
||||
{
|
||||
partValue -= digit * p;
|
||||
digit = partValue / n;
|
||||
output.Append((char)(digit + '0'));
|
||||
}
|
||||
|
||||
p = n;
|
||||
}
|
||||
|
||||
// Check for room for the '.'.
|
||||
if (intValue >= 1000000)
|
||||
return;
|
||||
|
||||
if (intValue < 100000)
|
||||
output.Append('.');
|
||||
|
||||
if (intValue >= 10000)
|
||||
return;
|
||||
|
||||
// Up to 5 fractional digits may be appended while keeping the total characters at 6.
|
||||
var fractionValue = (int)(value * 100000) - 100000 * intValue;
|
||||
for (var p = 10000; ;)
|
||||
{
|
||||
digit = fractionValue / p;
|
||||
output.Append((char)(digit + '0'));
|
||||
var n = p / 10;
|
||||
|
||||
// Stop if reached 6 characters total.
|
||||
if (intValue >= n)
|
||||
return;
|
||||
|
||||
fractionValue -= digit * p;
|
||||
p = n;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
var cr = Game.Renderer.RgbaColorRenderer;
|
||||
@@ -56,9 +145,31 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
}
|
||||
|
||||
k = 0;
|
||||
var maxExtraDotSpace = 0;
|
||||
var maxNameLength = 0;
|
||||
foreach (var item in PerfHistory.Items.Values)
|
||||
{
|
||||
Game.Renderer.Fonts["Tiny"].DrawText(item.Name, new float2(rect.Left, rect.Top) + new float2(18, 10 * k - 3), Color.White);
|
||||
maxExtraDotSpace = Math.Max(maxExtraDotSpace, textWidthCache[item.Name]);
|
||||
maxNameLength = Math.Max(maxNameLength, item.Name.Length);
|
||||
}
|
||||
|
||||
builder ??= new StringBuilder(Math.Max(20, maxExtraDotSpace + 3));
|
||||
maxExtraDotSpace = Math.Max(0, maxExtraDotSpace - dotWidth); // First dot is always printed.
|
||||
var columnTwoStart = maxExtraDotSpace + 3 * nextDotAdvance + 2;
|
||||
|
||||
foreach (var item in PerfHistory.Items.Values)
|
||||
{
|
||||
var nameWidth = textWidthCache[item.Name];
|
||||
var dotsNeeded = (maxExtraDotSpace - nameWidth) / nextDotAdvance + 3; // first + 2 extra dots for spacing before numbers.
|
||||
builder.Append(item.Name);
|
||||
builder.Append('.', dotsNeeded);
|
||||
font.DrawText(builder.ToString(), new float2(rect.Left, rect.Top) + new float2(18, 10 * k - 3), Color.White);
|
||||
builder.Clear();
|
||||
SixCharacterFormatFloat(builder, item.Average(Game.Settings.Debug.Samples));
|
||||
builder.Append(" : ");
|
||||
SixCharacterFormatFloat(builder, item.ActiveGameTotalAverage());
|
||||
font.DrawText(builder.ToString(), new float2(rect.Left, rect.Top) + new float2(18 + columnTwoStart, 10 * k - 3), Color.White);
|
||||
builder.Clear();
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user