PerfTickLogger, reduce overhead of logging long ticks.

This commit is contained in:
Vapre
2022-08-02 17:20:14 +02:00
committed by Matthias Mailänder
parent c095690619
commit edbded8f0a
5 changed files with 51 additions and 42 deletions

View File

@@ -13,36 +13,43 @@ using System.Diagnostics;
namespace OpenRA.Support
{
public sealed class PerfTickLogger
public static class PerfTickLogger
{
readonly DebugSettings settings = Game.Settings.Debug;
readonly long threshold = PerfTimer.LongTickThresholdInStopwatchTicks;
long start;
long current;
bool enabled;
public const long TimestampDisabled = 0L;
long CurrentTimestamp => enabled ? Stopwatch.GetTimestamp() : 0L;
static float durationThresholdMs = Game.Settings.Debug.LongTickThresholdMs;
static long durationThresholdTicks = PerfTimer.MillisToTicks(Game.Settings.Debug.LongTickThresholdMs);
public void Start()
/// <summary>Retrieve the current timestamp.</summary>
/// <returns>TimestampDisabled if performance logging is disabled.</returns>
public static long GetTimestamp()
{
enabled = settings.EnableSimulationPerfLogging;
start = CurrentTimestamp;
}
var settings = Game.Settings.Debug;
if (!settings.EnableSimulationPerfLogging)
return TimestampDisabled;
public void LogTickAndRestartTimer(string name, object item)
{
if (!enabled)
return;
current = CurrentTimestamp;
if (current - start > threshold)
// TODO: Let settings notify listeners on changes
if (durationThresholdMs != settings.LongTickThresholdMs)
{
PerfTimer.LogLongTick(start, current, name, item);
start = CurrentTimestamp;
return;
durationThresholdMs = Game.Settings.Debug.LongTickThresholdMs;
durationThresholdTicks = PerfTimer.MillisToTicks(durationThresholdMs);
}
start = current;
return Stopwatch.GetTimestamp();
}
/// <summary>Logs an entry in the performance log when the current time since the start tick exceeds the game debug setting `LongTickThresholdMs`.</summary>
/// <returns>TimestampDisabled if performance logging is disabled.</returns>
public static long LogLongTick(long startTimestamp, string name, object item)
{
if (startTimestamp == TimestampDisabled)
return TimestampDisabled;
var currentTimetamp = Stopwatch.GetTimestamp();
if (currentTimetamp - startTimestamp > durationThresholdTicks)
PerfTimer.LogLongTick(startTimestamp, currentTimetamp, name, item);
return currentTimetamp;
}
}
}

View File

@@ -24,8 +24,9 @@ namespace OpenRA.Support
const string IndentationString = "| ";
const string FormatSeperation = " ms ";
static readonly string FormatString = "{0," + Digits + ":0}" + FormatSeperation + "{1}";
static readonly string FormatStringLongTick = "{0," + Digits + ":0}" + FormatSeperation + "[{1}] {2}: {3}";
readonly string name;
readonly float thresholdMs;
readonly long thresholdTicks;
readonly byte depth;
readonly PerfTimer parent;
List<PerfTimer> children;
@@ -36,7 +37,7 @@ namespace OpenRA.Support
public PerfTimer(string name, float thresholdMs = 0)
{
this.name = name;
this.thresholdMs = thresholdMs;
thresholdTicks = MillisToTicks(thresholdMs);
parent = ParentThreadLocal.Value;
depth = parent == null ? (byte)0 : (byte)(parent.depth + 1);
@@ -53,7 +54,7 @@ namespace OpenRA.Support
if (parent == null)
Write();
else if (ElapsedMs > thresholdMs)
else if (ticks > thresholdTicks)
{
parent.children ??= new List<PerfTimer>();
parent.children.Add(this);
@@ -69,23 +70,28 @@ namespace OpenRA.Support
child.Write();
Log.Write("perf", string.Format(FormatString, ElapsedMs, GetFooter(Indentation)));
}
else if (ElapsedMs >= thresholdMs)
else if (ticks >= thresholdTicks)
Log.Write("perf", string.Format(FormatString, ElapsedMs, Indentation + name));
}
public static long MillisToTicks(float millis)
{
return (long)(Stopwatch.Frequency * millis / 1000f);
}
float ElapsedMs => 1000f * ticks / Stopwatch.Frequency;
public static void LogLongTick(long startStopwatchTicks, long endStopwatchTicks, string name, object item)
{
var type = item.GetType();
var label = type == typeof(string) || type.IsGenericType ? item.ToString() : type.Name;
Log.Write("perf", string.Format(FormatString,
Log.Write("perf", string.Format(FormatStringLongTick,
1000f * (endStopwatchTicks - startStopwatchTicks) / Stopwatch.Frequency,
"[" + Game.LocalTick + "] " + name + ": " + label));
Game.LocalTick,
name,
label));
}
public static long LongTickThresholdInStopwatchTicks => (long)(Stopwatch.Frequency * Game.Settings.Debug.LongTickThresholdMs / 1000f);
#region Formatting helpers
static string GetHeader(string indentation, string label)
{