use custom interpolated string handler
This commit is contained in:
@@ -368,7 +368,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_performanceCollector.LogPerformance(this, "FullFileScan", () => FullFileScan(token));
|
_performanceCollector.LogPerformance(this, $"FullFileScan", () => FullFileScan(token));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class PlayerDataFactory
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _performanceCollector.LogPerformance(this, "CreateCharacterData>" + playerRelatedObject.ObjectKind, async () =>
|
await _performanceCollector.LogPerformance(this, $"CreateCharacterData>{playerRelatedObject.ObjectKind}", async () =>
|
||||||
{
|
{
|
||||||
await CreateCharacterData(previousData, playerRelatedObject, token).ConfigureAwait(false);
|
await CreateCharacterData(previousData, playerRelatedObject, token).ConfigureAwait(false);
|
||||||
}).ConfigureAwait(true);
|
}).ConfigureAwait(true);
|
||||||
|
|||||||
@@ -374,8 +374,8 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_performanceCollector.LogPerformance(this, "CheckAndUpdateObject>" + (_isOwnedObject ? "Self+" : "Other+") + ObjectKind + "/"
|
_performanceCollector.LogPerformance(this, $"CheckAndUpdateObject>{(_isOwnedObject ? "Self" : "Other")}+{ObjectKind}/{(string.IsNullOrEmpty(Name) ? "Unk" : Name)}"
|
||||||
+ (string.IsNullOrEmpty(Name) ? "Unk" : Name) + "+" + Address.ToString("X"), CheckAndUpdateObject);
|
+ $"+{Address.ToString("X")}", CheckAndUpdateObject);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
|||||||
|
|
||||||
public async Task<string> GetPlayerNameHashedAsync()
|
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()
|
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)
|
public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(callerFilePath);
|
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)
|
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)
|
public async Task<T> RunOnFrameworkThread<T>(Func<T> func, [CallerMemberName] string callerMember = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(callerFilePath);
|
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)
|
if (!_framework.IsInFrameworkUpdateThread)
|
||||||
{
|
{
|
||||||
@@ -426,7 +426,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
|||||||
|
|
||||||
private void FrameworkOnUpdate(IFramework framework)
|
private void FrameworkOnUpdate(IFramework framework)
|
||||||
{
|
{
|
||||||
_performanceCollector.LogPerformance(this, "FrameworkOnUpdate", FrameworkOnUpdateInternal);
|
_performanceCollector.LogPerformance(this, $"FrameworkOnUpdate", FrameworkOnUpdateInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void FrameworkOnUpdateInternal()
|
private unsafe void FrameworkOnUpdateInternal()
|
||||||
@@ -438,10 +438,10 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
|||||||
|
|
||||||
bool isNormalFrameworkUpdate = DateTime.Now < _delayedFrameworkUpdateCheck.AddSeconds(1);
|
bool isNormalFrameworkUpdate = DateTime.Now < _delayedFrameworkUpdateCheck.AddSeconds(1);
|
||||||
|
|
||||||
_performanceCollector.LogPerformance(this, "FrameworkOnUpdateInternal+" + (isNormalFrameworkUpdate ? "Regular" : "Delayed"), () =>
|
_performanceCollector.LogPerformance(this, $"FrameworkOnUpdateInternal+{(isNormalFrameworkUpdate ? "Regular" : "Delayed")}", () =>
|
||||||
{
|
{
|
||||||
IsAnythingDrawing = false;
|
IsAnythingDrawing = false;
|
||||||
_performanceCollector.LogPerformance(this, "ObjTableToCharas",
|
_performanceCollector.LogPerformance(this, $"ObjTableToCharas",
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
_notUpdatedCharas.AddRange(_playerCharas.Keys);
|
_notUpdatedCharas.AddRange(_playerCharas.Keys);
|
||||||
@@ -453,7 +453,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
MemoryHelper.ReadStringNullTerminated((nint)((GameObject*)chara.Address)->Name, out string charaName);
|
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)
|
if (!IsAnythingDrawing)
|
||||||
CheckCharacterForDrawing(chara.Address, charaName);
|
CheckCharacterForDrawing(chara.Address, charaName);
|
||||||
_notUpdatedCharas.Remove(hash);
|
_notUpdatedCharas.Remove(hash);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public abstract class WindowMediatorSubscriberBase : Window, IMediatorSubscriber
|
|||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
_performanceCollectorService.LogPerformance(this, "Draw", DrawInternal);
|
_performanceCollectorService.LogPerformance(this, $"Draw", DrawInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void DrawInternal();
|
protected abstract void DrawInternal();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
private readonly ILogger<PerformanceCollectorService> _logger;
|
private readonly ILogger<PerformanceCollectorService> _logger;
|
||||||
private readonly MareConfigService _mareConfigService;
|
private readonly MareConfigService _mareConfigService;
|
||||||
public ConcurrentDictionary<string, RollingList<(TimeOnly, long)>> PerformanceCounters { get; } = new(StringComparer.Ordinal);
|
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)
|
public PerformanceCollectorService(ILogger<PerformanceCollectorService> logger, MareConfigService mareConfigService)
|
||||||
{
|
{
|
||||||
@@ -22,15 +22,15 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
_mareConfigService = mareConfigService;
|
_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();
|
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;
|
var dt = DateTime.UtcNow.Ticks;
|
||||||
@@ -43,21 +43,21 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
var elapsed = DateTime.UtcNow.Ticks - dt;
|
var elapsed = DateTime.UtcNow.Ticks - dt;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (TimeSpan.FromTicks(elapsed) > TimeSpan.FromMilliseconds(10))
|
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
|
#endif
|
||||||
list.Add((TimeOnly.FromDateTime(DateTime.Now), elapsed));
|
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; }
|
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;
|
var dt = DateTime.UtcNow.Ticks;
|
||||||
@@ -70,7 +70,7 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
var elapsed = DateTime.UtcNow.Ticks - dt;
|
var elapsed = DateTime.UtcNow.Ticks - dt;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (TimeSpan.FromTicks(elapsed) > TimeSpan.FromMilliseconds(10))
|
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
|
#endif
|
||||||
list.Add(new(TimeOnly.FromDateTime(DateTime.Now), elapsed));
|
list.Add(new(TimeOnly.FromDateTime(DateTime.Now), elapsed));
|
||||||
}
|
}
|
||||||
@@ -79,14 +79,15 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Starting PerformanceCollectorService");
|
_logger.LogInformation("Starting PerformanceCollectorService");
|
||||||
_ = Task.Run(PeriodicLogPrune, _periodicLogPruneTask.Token);
|
_ = Task.Run(PeriodicLogPrune, _periodicLogPruneTaskCts.Token);
|
||||||
_logger.LogInformation("Started PerformanceCollectorService");
|
_logger.LogInformation("Started PerformanceCollectorService");
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_periodicLogPruneTask.Cancel();
|
_periodicLogPruneTaskCts.Cancel();
|
||||||
|
_periodicLogPruneTaskCts.Dispose();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,9 +175,9 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
|
|
||||||
private async Task PeriodicLogPrune()
|
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())
|
foreach (var entries in PerformanceCounters.ToList())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
});
|
});
|
||||||
GameFont = _pluginInterface.UiBuilder.FontAtlas.NewGameFontHandle(new(GameFontFamilyAndSize.Axis12));
|
GameFont = _pluginInterface.UiBuilder.FontAtlas.NewGameFontHandle(new(GameFontFamilyAndSize.Axis12));
|
||||||
IconFont = _pluginInterface.UiBuilder.IconFontHandle;
|
IconFont = _pluginInterface.UiBuilder.IconFontHandle;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiController ApiController => _apiController;
|
public ApiController ApiController => _apiController;
|
||||||
@@ -294,9 +295,27 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
|
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)
|
private static bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public static class Crypto
|
|||||||
#pragma warning disable SYSLIB0021 // Type or member is obsolete
|
#pragma warning disable SYSLIB0021 // Type or member is obsolete
|
||||||
|
|
||||||
private static readonly Dictionary<string, string> _hashListSHA1 = new(StringComparer.Ordinal);
|
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 Dictionary<string, string> _hashListSHA256 = new(StringComparer.Ordinal);
|
||||||
private static readonly SHA256CryptoServiceProvider _sha256CryptoProvider = new();
|
private static readonly SHA256CryptoServiceProvider _sha256CryptoProvider = new();
|
||||||
private static readonly SHA1CryptoServiceProvider _sha1CryptoProvider = new();
|
private static readonly SHA1CryptoServiceProvider _sha1CryptoProvider = new();
|
||||||
@@ -23,6 +24,15 @@ public static class Crypto
|
|||||||
return GetOrComputeHashSHA1(stringToHash);
|
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)
|
public static string GetHash256(this string stringToHash)
|
||||||
{
|
{
|
||||||
return GetOrComputeHashSHA256(stringToHash);
|
return GetOrComputeHashSHA256(stringToHash);
|
||||||
|
|||||||
27
MareSynchronos/Utils/MareInterpolatedStringHandler.cs
Normal file
27
MareSynchronos/Utils/MareInterpolatedStringHandler.cs
Normal 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();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user