use custom interpolated string handler

This commit is contained in:
rootdarkarchon
2024-03-19 12:37:20 +01:00
parent 4a04513652
commit 86cdcdb5cf
9 changed files with 88 additions and 31 deletions

View File

@@ -368,7 +368,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
{
try
{
_performanceCollector.LogPerformance(this, "FullFileScan", () => FullFileScan(token));
_performanceCollector.LogPerformance(this, $"FullFileScan", () => FullFileScan(token));
}
catch (Exception ex)
{

View File

@@ -76,7 +76,7 @@ public class PlayerDataFactory
try
{
await _performanceCollector.LogPerformance(this, "CreateCharacterData>" + playerRelatedObject.ObjectKind, async () =>
await _performanceCollector.LogPerformance(this, $"CreateCharacterData>{playerRelatedObject.ObjectKind}", async () =>
{
await CreateCharacterData(previousData, playerRelatedObject, token).ConfigureAwait(false);
}).ConfigureAwait(true);

View File

@@ -374,8 +374,8 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
try
{
_performanceCollector.LogPerformance(this, "CheckAndUpdateObject>" + (_isOwnedObject ? "Self+" : "Other+") + ObjectKind + "/"
+ (string.IsNullOrEmpty(Name) ? "Unk" : Name) + "+" + Address.ToString("X"), CheckAndUpdateObject);
_performanceCollector.LogPerformance(this, $"CheckAndUpdateObject>{(_isOwnedObject ? "Self" : "Other")}+{ObjectKind}/{(string.IsNullOrEmpty(Name) ? "Unk" : Name)}"
+ $"+{Address.ToString("X")}", CheckAndUpdateObject);
}
catch (Exception ex)
{

View File

@@ -197,7 +197,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public async Task<string> GetPlayerNameHashedAsync()
{
return await RunOnFrameworkThread(() => (GetPlayerName() + GetHomeWorldId()).GetHash256()).ConfigureAwait(false);
return await RunOnFrameworkThread(() => (GetPlayerName(), (ushort)GetHomeWorldId()).GetHash256()).ConfigureAwait(false);
}
public IntPtr GetPlayerPointer()
@@ -252,7 +252,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
{
var fileName = Path.GetFileNameWithoutExtension(callerFilePath);
await _performanceCollector.LogPerformance(this, "RunOnFramework:Act/" + fileName + ">" + callerMember + ":" + callerLineNumber, async () =>
await _performanceCollector.LogPerformance(this, $"RunOnFramework:Act/{fileName}>{callerMember}:{callerLineNumber}", async () =>
{
if (!_framework.IsInFrameworkUpdateThread)
{
@@ -271,7 +271,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public async Task<T> RunOnFrameworkThread<T>(Func<T> func, [CallerMemberName] string callerMember = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
{
var fileName = Path.GetFileNameWithoutExtension(callerFilePath);
return await _performanceCollector.LogPerformance(this, "RunOnFramework:Func<" + typeof(T) + ">/" + fileName + ">" + callerMember + ":" + callerLineNumber, async () =>
return await _performanceCollector.LogPerformance(this, $"RunOnFramework:Func<{typeof(T)}>/{fileName}>{callerMember}:{callerLineNumber}", async () =>
{
if (!_framework.IsInFrameworkUpdateThread)
{
@@ -426,7 +426,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
private void FrameworkOnUpdate(IFramework framework)
{
_performanceCollector.LogPerformance(this, "FrameworkOnUpdate", FrameworkOnUpdateInternal);
_performanceCollector.LogPerformance(this, $"FrameworkOnUpdate", FrameworkOnUpdateInternal);
}
private unsafe void FrameworkOnUpdateInternal()
@@ -438,10 +438,10 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
bool isNormalFrameworkUpdate = DateTime.Now < _delayedFrameworkUpdateCheck.AddSeconds(1);
_performanceCollector.LogPerformance(this, "FrameworkOnUpdateInternal+" + (isNormalFrameworkUpdate ? "Regular" : "Delayed"), () =>
_performanceCollector.LogPerformance(this, $"FrameworkOnUpdateInternal+{(isNormalFrameworkUpdate ? "Regular" : "Delayed")}", () =>
{
IsAnythingDrawing = false;
_performanceCollector.LogPerformance(this, "ObjTableToCharas",
_performanceCollector.LogPerformance(this, $"ObjTableToCharas",
() =>
{
_notUpdatedCharas.AddRange(_playerCharas.Keys);
@@ -453,7 +453,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
continue;
MemoryHelper.ReadStringNullTerminated((nint)((GameObject*)chara.Address)->Name, out string charaName);
var hash = (charaName + ((BattleChara*)chara.Address)->Character.HomeWorld.ToString()).GetHash256();
var hash = (charaName, ((BattleChara*)chara.Address)->Character.HomeWorld).GetHash256();
if (!IsAnythingDrawing)
CheckCharacterForDrawing(chara.Address, charaName);
_notUpdatedCharas.Remove(hash);

View File

@@ -35,7 +35,7 @@ public abstract class WindowMediatorSubscriberBase : Window, IMediatorSubscriber
public override void Draw()
{
_performanceCollectorService.LogPerformance(this, "Draw", DrawInternal);
_performanceCollectorService.LogPerformance(this, $"Draw", DrawInternal);
}
protected abstract void DrawInternal();

View File

@@ -14,7 +14,7 @@ public sealed class PerformanceCollectorService : IHostedService
private readonly ILogger<PerformanceCollectorService> _logger;
private readonly MareConfigService _mareConfigService;
public ConcurrentDictionary<string, RollingList<(TimeOnly, long)>> PerformanceCounters { get; } = new(StringComparer.Ordinal);
private readonly CancellationTokenSource _periodicLogPruneTask = new();
private readonly CancellationTokenSource _periodicLogPruneTaskCts = new();
public PerformanceCollectorService(ILogger<PerformanceCollectorService> logger, MareConfigService mareConfigService)
{
@@ -22,15 +22,15 @@ public sealed class PerformanceCollectorService : IHostedService
_mareConfigService = mareConfigService;
}
public T LogPerformance<T>(object sender, string counterName, Func<T> func, int maxEntries = 10000)
public T LogPerformance<T>(object sender, MareInterpolatedStringHandler counterName, Func<T> func, int maxEntries = 10000)
{
if (!_mareConfigService.Current.LogPerformance) return func.Invoke();
counterName = sender.GetType().Name + _counterSplit + counterName;
string cn = sender.GetType().Name + _counterSplit + counterName.BuildMessage();
if (!PerformanceCounters.TryGetValue(counterName, out var list))
if (!PerformanceCounters.TryGetValue(cn, out var list))
{
list = PerformanceCounters[counterName] = new(maxEntries);
list = PerformanceCounters[cn] = new(maxEntries);
}
var dt = DateTime.UtcNow.Ticks;
@@ -43,21 +43,21 @@ public sealed class PerformanceCollectorService : IHostedService
var elapsed = DateTime.UtcNow.Ticks - dt;
#if DEBUG
if (TimeSpan.FromTicks(elapsed) > TimeSpan.FromMilliseconds(10))
_logger.LogWarning(">10ms spike on {counterName}: {time}", counterName, TimeSpan.FromTicks(elapsed));
_logger.LogWarning(">10ms spike on {counterName}: {time}", cn, TimeSpan.FromTicks(elapsed));
#endif
list.Add((TimeOnly.FromDateTime(DateTime.Now), elapsed));
}
}
public void LogPerformance(object sender, string counterName, Action act, int maxEntries = 10000)
public void LogPerformance(object sender, MareInterpolatedStringHandler counterName, Action act, int maxEntries = 10000)
{
if (!_mareConfigService.Current.LogPerformance) { act.Invoke(); return; }
counterName = sender.GetType().Name + _counterSplit + counterName;
var cn = sender.GetType().Name + _counterSplit + counterName.BuildMessage();
if (!PerformanceCounters.TryGetValue(counterName, out var list))
if (!PerformanceCounters.TryGetValue(cn, out var list))
{
list = PerformanceCounters[counterName] = new(maxEntries);
list = PerformanceCounters[cn] = new(maxEntries);
}
var dt = DateTime.UtcNow.Ticks;
@@ -70,7 +70,7 @@ public sealed class PerformanceCollectorService : IHostedService
var elapsed = DateTime.UtcNow.Ticks - dt;
#if DEBUG
if (TimeSpan.FromTicks(elapsed) > TimeSpan.FromMilliseconds(10))
_logger.LogWarning(">10ms spike on {counterName}: {time}", counterName, TimeSpan.FromTicks(elapsed));
_logger.LogWarning(">10ms spike on {counterName}: {time}", cn, TimeSpan.FromTicks(elapsed));
#endif
list.Add(new(TimeOnly.FromDateTime(DateTime.Now), elapsed));
}
@@ -79,14 +79,15 @@ public sealed class PerformanceCollectorService : IHostedService
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting PerformanceCollectorService");
_ = Task.Run(PeriodicLogPrune, _periodicLogPruneTask.Token);
_ = Task.Run(PeriodicLogPrune, _periodicLogPruneTaskCts.Token);
_logger.LogInformation("Started PerformanceCollectorService");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_periodicLogPruneTask.Cancel();
_periodicLogPruneTaskCts.Cancel();
_periodicLogPruneTaskCts.Dispose();
return Task.CompletedTask;
}
@@ -174,9 +175,9 @@ public sealed class PerformanceCollectorService : IHostedService
private async Task PeriodicLogPrune()
{
while (!_periodicLogPruneTask.Token.IsCancellationRequested)
while (!_periodicLogPruneTaskCts.Token.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromMinutes(10), _periodicLogPruneTask.Token).ConfigureAwait(false);
await Task.Delay(TimeSpan.FromMinutes(10), _periodicLogPruneTaskCts.Token).ConfigureAwait(false);
foreach (var entries in PerformanceCounters.ToList())
{

View File

@@ -114,6 +114,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
});
GameFont = _pluginInterface.UiBuilder.FontAtlas.NewGameFontHandle(new(GameFontFamilyAndSize.Axis12));
IconFont = _pluginInterface.UiBuilder.IconFontHandle;
}
public ApiController ApiController => _apiController;
@@ -294,9 +295,27 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
}
public static bool IconButton(FontAwesomeIcon icon)
public static bool IconButton(FontAwesomeIcon icon, float? height = null)
{
return ImGuiComponents.IconButton(icon);
string text = icon.ToIconString();
ImGui.PushID(text);
ImGui.PushFont(UiBuilder.IconFont);
Vector2 vector = ImGui.CalcTextSize(text);
ImGui.PopFont();
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = vector.X + ImGui.GetStyle().FramePadding.X * 2f;
float frameHeight = height ?? ImGui.GetFrameHeight();
bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight));
Vector2 pos = new Vector2(cursorScreenPos.X + ImGui.GetStyle().FramePadding.X,
cursorScreenPos.Y + (height ?? ImGui.GetFrameHeight()) / 2f - (vector.Y / 2f));
ImGui.PushFont(UiBuilder.IconFont);
windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), text);
ImGui.PopFont();
ImGui.PopID();
return result;
}
private static bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null)

View File

@@ -8,6 +8,7 @@ public static class Crypto
#pragma warning disable SYSLIB0021 // Type or member is obsolete
private static readonly Dictionary<string, string> _hashListSHA1 = new(StringComparer.Ordinal);
private static readonly Dictionary<(string, ushort), string> _hashListPlayersSHA256 = new();
private static readonly Dictionary<string, string> _hashListSHA256 = new(StringComparer.Ordinal);
private static readonly SHA256CryptoServiceProvider _sha256CryptoProvider = new();
private static readonly SHA1CryptoServiceProvider _sha1CryptoProvider = new();
@@ -23,6 +24,15 @@ public static class Crypto
return GetOrComputeHashSHA1(stringToHash);
}
public static string GetHash256(this (string, ushort) playerToHash)
{
if (_hashListPlayersSHA256.TryGetValue(playerToHash, out var hash))
return hash;
return _hashListPlayersSHA256[playerToHash] =
BitConverter.ToString(_sha256CryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(playerToHash.Item1 + playerToHash.Item2.ToString()))).Replace("-", "", StringComparison.Ordinal);
}
public static string GetHash256(this string stringToHash)
{
return GetOrComputeHashSHA256(stringToHash);
@@ -33,7 +43,7 @@ public static class Crypto
if (_hashListSHA256.TryGetValue(stringToCompute, out var hash))
return hash;
return _hashListSHA256[stringToCompute] =
return _hashListSHA256[stringToCompute] =
BitConverter.ToString(_sha256CryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal);
}
@@ -42,7 +52,7 @@ public static class Crypto
if (_hashListSHA1.TryGetValue(stringToCompute, out var hash))
return hash;
return _hashListSHA1[stringToCompute] =
return _hashListSHA1[stringToCompute] =
BitConverter.ToString(_sha1CryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal);
}
#pragma warning restore SYSLIB0021 // Type or member is obsolete

View File

@@ -0,0 +1,27 @@
using System.Runtime.CompilerServices;
using System.Text;
namespace MareSynchronos.Utils;
[InterpolatedStringHandler]
public readonly ref struct MareInterpolatedStringHandler
{
readonly StringBuilder _logMessageStringbuilder;
public MareInterpolatedStringHandler(int literalLength, int formattedCount)
{
_logMessageStringbuilder = new StringBuilder(literalLength);
}
public void AppendLiteral(string s)
{
_logMessageStringbuilder.Append(s);
}
public void AppendFormatted<T>(T t)
{
_logMessageStringbuilder.Append(t?.ToString());
}
public string BuildMessage() => _logMessageStringbuilder.ToString();
}