diff --git a/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs b/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs index 9f6dd85..8dd20f7 100644 --- a/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs +++ b/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs @@ -33,20 +33,19 @@ internal sealed class GameTickWorker( private async Task RunAsync() { + // do not block in StartAsync + await Task.Delay(1).ConfigureAwait(false); + try { var sw = new Stopwatch(); while (!_cancellation.IsCancellationRequested) { - logger.LogTrace("since last frame: {}", sw.Elapsed); - var delta = sw.Elapsed; sw.Restart(); foreach (var step in _steps) await step.TickAsync(delta); - - await Task.Delay(1); } } catch (Exception ex) diff --git a/tanks-backend/TanksServer/GameLogic/UpdatesPerSecondCounter.cs b/tanks-backend/TanksServer/GameLogic/UpdatesPerSecondCounter.cs new file mode 100644 index 0000000..adfdc9b --- /dev/null +++ b/tanks-backend/TanksServer/GameLogic/UpdatesPerSecondCounter.cs @@ -0,0 +1,54 @@ +using System.Diagnostics; + +namespace TanksServer.GameLogic; + +internal sealed class UpdatesPerSecondCounter(ILogger logger) : ITickStep +{ + private readonly Stopwatch _long = Stopwatch.StartNew(); + private ulong _updatesSinceLongReset; + private TimeSpan _minFrameTime = TimeSpan.MaxValue; + private TimeSpan _maxFrameTime = TimeSpan.MinValue; + + public ValueTask TickAsync(TimeSpan delta) + { + if (logger.IsEnabled(LogLevel.Trace)) + logger.LogTrace("time since last update: {}", delta); + if (delta.TotalSeconds > 1) + logger.LogCritical("single update took {}", delta); + + if (_minFrameTime > delta) + _minFrameTime = delta; + if (_maxFrameTime < delta) + _maxFrameTime = delta; + + _updatesSinceLongReset++; + + if (_long.Elapsed.TotalSeconds < 10) + return ValueTask.CompletedTask; + + LogCounters(); + ResetCounters(); + return ValueTask.CompletedTask; + } + + private void LogCounters() + { + if (!logger.IsEnabled(LogLevel.Debug)) + return; + + var time = _long.Elapsed; + var average = Math.Round(_updatesSinceLongReset / time.TotalSeconds); + var min = Math.Round(1 / _maxFrameTime.TotalSeconds); + var max = Math.Round(1 / _minFrameTime.TotalSeconds); + logger.LogDebug("UPS stats for {} updates in {}: avg={}, min={}, max={}", + _updatesSinceLongReset, time, average, min, max); + } + + private void ResetCounters() + { + _long.Restart(); + _updatesSinceLongReset = 0; + _minFrameTime = TimeSpan.MaxValue; + _maxFrameTime = TimeSpan.MinValue; + } +} diff --git a/tanks-backend/TanksServer/Program.cs b/tanks-backend/TanksServer/Program.cs index edff439..cce672b 100644 --- a/tanks-backend/TanksServer/Program.cs +++ b/tanks-backend/TanksServer/Program.cs @@ -78,6 +78,7 @@ public static class Program builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => sp.GetRequiredService()); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/tanks-backend/TanksServer/appsettings.json b/tanks-backend/TanksServer/appsettings.json index dd8aa6d..37f8c7b 100644 --- a/tanks-backend/TanksServer/appsettings.json +++ b/tanks-backend/TanksServer/appsettings.json @@ -3,8 +3,8 @@ "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning", - "TanksServer": "Debug", - "Microsoft.AspNetCore.HttpLogging": "Information" + "TanksServer": "Information", + "TanksServer.GameLogic.UpdatesPerSecondCounter": "Debug" } }, "AllowedHosts": "*", @@ -33,7 +33,7 @@ "SmartBulletHomingSpeed": 1.5 }, "Host": { - "EnableServicePointDisplay": true, + "EnableServicePointDisplay": false, "ServicePointDisplayMinFrameTimeMs": 28, "ClientScreenMinFrameTime": 5 } diff --git a/tanks-backend/global.json b/tanks-backend/global.json index dad2db5..8eb62be 100644 --- a/tanks-backend/global.json +++ b/tanks-backend/global.json @@ -1,7 +1,6 @@ { "sdk": { "version": "8.0.0", - "rollForward": "latestMajor", - "allowPrerelease": true + "rollForward": "latestMajor" } -} \ No newline at end of file +}