From 7c3a2dab89293cc1bc5bac1a914eb93940a26d9e Mon Sep 17 00:00:00 2001 From: edmand46 Date: Sun, 5 Oct 2025 23:28:09 +0300 Subject: [PATCH] feat: optimize game server tick loop performance --- Ragon.Relay/Sources/Relay.cs | 29 +++++++++++++++++++++++++---- Ragon.Server/Sources/RagonServer.cs | 24 ++++-------------------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Ragon.Relay/Sources/Relay.cs b/Ragon.Relay/Sources/Relay.cs index d9b0e77..20e1598 100644 --- a/Ragon.Relay/Sources/Relay.cs +++ b/Ragon.Relay/Sources/Relay.cs @@ -15,6 +15,7 @@ */ using System; +using System.Diagnostics; using System.IO; using System.Threading; using Newtonsoft.Json; @@ -40,9 +41,9 @@ namespace Ragon.Relay var configuration = JsonConvert.DeserializeObject(data); var serverType = RagonServerConfiguration.GetServerType(configuration.ServerType); - INetworkServer networkServer = new ENetServer(); + INetworkServer networkServer; IServerPlugin plugin = new RelayServerPlugin(); - + switch (serverType) { case ServerType.ENET: @@ -51,6 +52,9 @@ namespace Ragon.Relay case ServerType.WEBSOCKET: networkServer = new WebSocketServer(); break; + default: + networkServer = new ENetServer(); + break; } var serverConfiguration = new RagonServerConfiguration() @@ -67,13 +71,30 @@ namespace Ragon.Relay ServerTickRate = configuration.ServerTickRate, ServerAddress = configuration.ServerAddress, }; - + var relay = new RagonServer(networkServer, plugin, serverConfiguration); relay.Start(); + + var sw = Stopwatch.StartNew(); + var tickRateMs = 1000.0 / configuration.ServerTickRate; + var nextTickMs = tickRateMs; + while (relay.IsRunning) { relay.Tick(); - Thread.Sleep(1); + + var sleepTime = nextTickMs - sw.Elapsed.TotalMilliseconds; + if (sleepTime > 0) + { + Thread.Sleep((int)sleepTime); + } + + nextTickMs += tickRateMs; + + if (nextTickMs < sw.Elapsed.TotalMilliseconds) + { + nextTickMs = sw.Elapsed.TotalMilliseconds + tickRateMs; + } } relay.Dispose(); diff --git a/Ragon.Server/Sources/RagonServer.cs b/Ragon.Server/Sources/RagonServer.cs index 4ebc188..4fc52ea 100644 --- a/Ragon.Server/Sources/RagonServer.cs +++ b/Ragon.Server/Sources/RagonServer.cs @@ -42,9 +42,7 @@ public class RagonServer : IRagonServer, INetworkListener private readonly Dictionary _contextsByConnection; private readonly Dictionary _contextsByPlayerId; private readonly ProjectRegistry _projectRegistry; - private readonly Stopwatch _timer; private readonly RagonLobbyDispatcher _lobbySerializer; - private readonly long _tickRate = 0; private bool _isRunning = false; public bool IsRunning => _isRunning; @@ -66,13 +64,12 @@ public class RagonServer : IRagonServer, INetworkListener _scheduler = new RagonScheduler(); _reader = new RagonBuffer(); _writer = new RagonBuffer(); - _tickRate = 1000 / _configuration.ServerTickRate; - _timer = new Stopwatch(); - + var contextObserver = new RagonContextObserver(_contextsByPlayerId); _scheduler.Run(new RagonActionTimer(SendRoomList, 2.0f)); _scheduler.Run(new RagonActionTimer(SendPlayerUserData, 0.1f)); _scheduler.Run(new RagonActionTimer(SendRoomUserData, 0.1f)); + _scheduler.Run(new RagonActionTimer(SendTimestamp, 1.0f / _configuration.ServerTickRate)); _serverPlugin.OnAttached(this); @@ -98,19 +95,8 @@ public class RagonServer : IRagonServer, INetworkListener } public void Tick() { - if (_timer.ElapsedMilliseconds > _tickRate * 2) - { - _logger.Warning($"Slow performance: {_timer.ElapsedMilliseconds}"); - } - - if (_timer.ElapsedMilliseconds > _tickRate) - { - _timer.Restart(); - _scheduler.Update(_timer.ElapsedMilliseconds / 1000.0f); - - SendTimestamp(); - } - + var deltaTime = 1.0f / _configuration.ServerTickRate; + _scheduler.Update(deltaTime); _server.Update(); } @@ -129,8 +115,6 @@ public class RagonServer : IRagonServer, INetworkListener _server.Listen(this, networkConfiguration); _serverPlugin.OnAttached(this); - _timer.Start(); - _isRunning = true; }