A comment that reads "MUST stay in lockstep with TryGetActiveCrossfade (K8)" helps nobody outside the plan that used to have a K8 in it, and the plans are not in this repo. Same for "Spec FR-4", "plan §B.2", "Sub-Task 4.4" and the F/R/M/A/S round codes scattered through the style engine and the self-tests. Personal names go too. "tester feedback from Jin (v1.4.7)" and "Flo decision 2026-06-15" carry the reason fine without naming anyone -- the version and the reason are the parts a reader can act on, and a public repo should not need a cast list to be read. The rule applied throughout: keep the why, drop the reference. Version numbers stay, since those resolve through the changelog. 77 files. ChunkUtil also carried 281 lines of commented-out code -- an older ToChunks variant and two helpers with no callers, inherited and never removed. Deleted; git remembers them.
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 B5 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);
|
|
}
|
|
}
|