use custom interpolated string handler

This commit is contained in:
rootdarkarchon
2024-03-19 12:37:20 +01:00
committed by Loporrit
parent b10bd444d1
commit 94e104939e
7 changed files with 53 additions and 25 deletions

View File

@@ -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)
{ {

View File

@@ -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);

View File

@@ -381,8 +381,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)
{ {

View File

@@ -270,7 +270,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)
{ {
@@ -289,7 +289,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)
{ {
@@ -467,7 +467,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()
@@ -479,10 +479,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",
() => () =>
{ {
if (_sentBetweenAreas) if (_sentBetweenAreas)

View File

@@ -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();

View File

@@ -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())
{ {

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();
}