The first sweep matched a character class that swallowed the digit, so a bare B1 slipped through while B1-2 was caught. Searching the whole A-Z space instead of guessing prefixes turned up 130-odd more: B0 through B6, C2, C3, D1, H2, M6, P7, P8, T2, W2, plus GP-04, KB-01, OD-1, PM-1, PM-3, SEC-01, TR-4, TR-7, UI-11, UI-12, XC-8 and API-3. Kept deliberately: 41 B4 01 is a byte signature, "N0" a format string, #L119-L128 a source anchor, LS4/LS6 are linkshells, and A=FF B=0C G=41 R=C2 explains a colour-channel order. Those look like codes and are not. Also translated the eight German comments left in the theme files and ImGuiUtil. Seven of them described what a palette does to which channel, which is worth reading -- just not in a second language in an otherwise English codebase.
69 lines
2.2 KiB
C#
69 lines
2.2 KiB
C#
using System.Globalization;
|
|
using System.IO;
|
|
|
|
namespace HellionChat.SelfTests;
|
|
|
|
// Disk sink for the performance baseline. Kept separate from the SelfTest
|
|
// step so the per-frame hot path never references file IO. Writes one
|
|
// perf-baseline.json into the plugin ConfigDirectory, atomically (tmp + move)
|
|
// like ThemeRegistry's theme writer, so a mid-write crash leaves either the
|
|
// old file or the new file, never a half JSON. Field names track the performance-baseline layout:
|
|
// steady-state Draw cost (avg/max ms), the quad-proxy draw-call count
|
|
// (avg/max), and frame delta (avg/max). First-frame-HITCH is read off
|
|
// drawMs max/avg by the human author, platform-annotated in the notes.
|
|
internal static class PerformanceBaselineLog
|
|
{
|
|
internal static string Write(
|
|
double avgDrawMs,
|
|
double maxDrawMs,
|
|
double avgDrawCallsProxy,
|
|
double maxDrawCallsProxy,
|
|
double avgDeltaMs,
|
|
double maxDeltaMs,
|
|
int frames
|
|
)
|
|
{
|
|
var targetPath = Path.Join(Plugin.Interface.ConfigDirectory.FullName, "perf-baseline.json");
|
|
|
|
var json =
|
|
"{\n"
|
|
+ $" \"frames\": {frames},\n"
|
|
+ $" \"avgDrawMs\": {Fmt(avgDrawMs)},\n"
|
|
+ $" \"maxDrawMs\": {Fmt(maxDrawMs)},\n"
|
|
+ $" \"avgDrawCallsProxy\": {Fmt(avgDrawCallsProxy)},\n"
|
|
+ $" \"maxDrawCallsProxy\": {Fmt(maxDrawCallsProxy)},\n"
|
|
+ $" \"avgDeltaMs\": {Fmt(avgDeltaMs)},\n"
|
|
+ $" \"maxDeltaMs\": {Fmt(maxDeltaMs)}\n"
|
|
+ "}\n";
|
|
|
|
// Atomic replace — same volume rename is atomic on POSIX and Windows.
|
|
var tmpPath = targetPath + ".tmp";
|
|
File.WriteAllText(tmpPath, json);
|
|
try
|
|
{
|
|
File.Move(tmpPath, targetPath, overwrite: true);
|
|
}
|
|
catch
|
|
{
|
|
// Avoid .tmp litter if Move fails (target locked).
|
|
try
|
|
{
|
|
File.Delete(tmpPath);
|
|
}
|
|
catch
|
|
{
|
|
// best effort
|
|
}
|
|
|
|
throw;
|
|
}
|
|
|
|
return targetPath;
|
|
}
|
|
|
|
private static string Fmt(double value)
|
|
{
|
|
return value.ToString("F2", CultureInfo.InvariantCulture);
|
|
}
|
|
}
|