From 56c348ac6865657f8b02c58864ee4652b8233219 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Fri, 17 Sep 2021 00:15:16 -0700 Subject: [PATCH] fix: Adds idle cpu config and forces on in debug (#790) * Adds `core.enableIdleCPU` to modernuo.json * Forces idle CPU on in DEBUG * Reverts idle detection back to CPS --- Projects/Server/EventLoopTasks.cs | 10 ++--- Projects/Server/Items/Item.cs | 8 +--- Projects/Server/Main.cs | 47 +++++++++++++------- Projects/Server/Mobiles/Mobile.cs | 8 +--- Projects/Server/Network/NetState/NetState.cs | 41 +++++------------ Projects/Server/Network/TcpServer.cs | 4 +- Projects/Server/Timer/Timer.TimerWheel.cs | 14 ++---- 7 files changed, 52 insertions(+), 80 deletions(-) diff --git a/Projects/Server/EventLoopTasks.cs b/Projects/Server/EventLoopTasks.cs index 3ead229cb..12f5ac664 100644 --- a/Projects/Server/EventLoopTasks.cs +++ b/Projects/Server/EventLoopTasks.cs @@ -55,7 +55,7 @@ namespace Server evt.WaitOne(); } - public int ExecuteTasks() + public void ExecuteTasks() { if (Thread.CurrentThread != _mainThread) { @@ -66,15 +66,11 @@ namespace Server for (int i = 0; i < count; i++) { - if (!_queue.TryDequeue(out var a)) + if (_queue.TryDequeue(out var a)) { - return count; + a(); } - - a(); } - - return count; } } } diff --git a/Projects/Server/Items/Item.cs b/Projects/Server/Items/Item.cs index 7d507b93a..d6d023cf7 100644 --- a/Projects/Server/Items/Item.cs +++ b/Projects/Server/Items/Item.cs @@ -3249,10 +3249,8 @@ namespace Server m_DeltaFlags &= ~flags; } - public static int ProcessDeltaQueue() + public static void ProcessDeltaQueue() { - int count = 0; - var limit = m_DeltaQueue.Count; while (m_DeltaQueue.Count > 0 && --limit >= 0) @@ -3264,8 +3262,6 @@ namespace Server continue; } - count++; - item.SetFlag(ImplFlag.InQueue, false); try @@ -3286,8 +3282,6 @@ namespace Server Console.WriteLine("Warning: {0} items left in delta queue after processing.", m_DeltaQueue.Count); Utility.PopColor(); } - - return count; } public virtual void OnDelete() diff --git a/Projects/Server/Main.cs b/Projects/Server/Main.cs index 18804b003..41bc0f858 100644 --- a/Projects/Server/Main.cs +++ b/Projects/Server/Main.cs @@ -155,6 +155,11 @@ namespace Server set => _now = value; } + private static long _cycleIndex = 1; + private static float[] _cyclesPerSecond = new float[100]; + + public static float CyclesPerSecond => _cyclesPerSecond[(_cycleIndex - 1) % _cyclesPerSecond.Length]; + public static bool MultiProcessor { get; private set; } public static int ProcessorCount { get; private set; } @@ -488,40 +493,52 @@ namespace Server { try { +#if DEBUG + var idleCPU = true; +#else + var idleCPU = ServerConfiguration.GetOrUpdateSetting("core.enableIdleCPU", false); +#endif + + long last = TickCount; const int interval = 100; - int idleCount = 0; + const float ticksPerSecond = 1000 * interval; + + int sample = 0; while (!Closing) { _tickCount = TickCount; _now = DateTime.UtcNow; - var events = Mobile.ProcessDeltaQueue(); - events += Item.ProcessDeltaQueue(); - events += Timer.Slice(_tickCount); + Mobile.ProcessDeltaQueue(); + Item.ProcessDeltaQueue(); + Timer.Slice(_tickCount); // Handle networking - events += TcpServer.Slice(); - events += NetState.HandleAllReceives(); - events += NetState.Slice(); + TcpServer.Slice(); + NetState.HandleAllReceives(); + NetState.Slice(); // Execute captured post-await methods (like Timer.Pause) - events += LoopContext.ExecuteTasks(); + LoopContext.ExecuteTasks(); Timer.CheckTimerPool(); // Check for pool depletion so we can async refill it. _tickCount = 0; _now = DateTime.MinValue; - if (events > 0) + if (idleCPU && ++sample % interval == 0) { - idleCount = 0; - continue; - } + var now = TickCount; - if (++idleCount > interval) - { - Thread.Sleep(1); + var cyclesPerSecond = ticksPerSecond / (now - last); + _cyclesPerSecond[_cycleIndex++ % _cyclesPerSecond.Length] = cyclesPerSecond; + last = now; + + if (cyclesPerSecond > 80) + { + Thread.Sleep(2); + } } } } diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index d4164130c..451a173ad 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -7848,10 +7848,8 @@ namespace Server } } - public static int ProcessDeltaQueue() + public static void ProcessDeltaQueue() { - int count = 0; - var limit = m_DeltaQueue.Count; while (m_DeltaQueue.Count > 0 && --limit >= 0) @@ -7863,8 +7861,6 @@ namespace Server continue; } - count++; - mob.m_InDeltaQueue = false; try @@ -7885,8 +7881,6 @@ namespace Server Console.WriteLine("Warning: {0} mobiles left in delta queue after processing.", m_DeltaQueue.Count); Utility.PopColor(); } - - return count; } public virtual void OnKillsChange(int oldValue) diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 84ce948be..c60147f81 100644 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -538,16 +538,13 @@ namespace Server.Network ThreadPool.UnsafeQueueUserWorkItem(SendTask, null); } - // Return true if there was any data to be processed. False otherwise. Used for idle detection. - public bool HandleReceive() + public void HandleReceive() { if (!Running) { - return false; + return; } - bool active = false; - var reader = RecvPipe.Reader; try @@ -563,9 +560,6 @@ namespace Server.Network break; } - // There was at least some data found, so it's not idle. - active = true; - var packetReader = new CircularBufferReader(result.Buffer); var packetId = packetReader.ReadByte(); int packetLength = length; @@ -583,7 +577,7 @@ namespace Server.Network case ProtocolState.Uninitialized: { HandleError(packetId, packetLength); - return true; + return; } case ProtocolState.AwaitingSeed: @@ -604,7 +598,7 @@ namespace Server.Network if (seed == 0) { HandleError(0, 0); - return true; + return; } _seed = seed; @@ -626,7 +620,7 @@ namespace Server.Network { LogInfo("Possible encrypted client detected, disconnecting..."); HandleError(packetId, packetLength); - return true; + return; } _parserState = ParserState.ProcessingPacket; @@ -643,7 +637,7 @@ namespace Server.Network if (packetId != 0xA0) { HandleError(packetId, packetLength); - return true; + return; } _parserState = ParserState.ProcessingPacket; @@ -665,7 +659,7 @@ namespace Server.Network _parserState = ParserState.AwaitingNextPacket; _protocolState = ProtocolState.AwaitingSeed; #endif - return true; + return; } case ProtocolState.GameServer_AwaitingGameServerLogin: @@ -673,7 +667,7 @@ namespace Server.Network if (packetId != 0x91 && packetId != 0x80) { HandleError(packetId, packetLength); - return true; + return; } _parserState = ParserState.ProcessingPacket; @@ -719,8 +713,6 @@ namespace Server.Network TraceException(ex); Disconnect("Exception during HandleReceive"); } - - return active; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -962,19 +954,12 @@ namespace Server.Network } } - public static int HandleAllReceives() + public static void HandleAllReceives() { - int count = 0; - foreach (var ns in TcpServer.Instances) { - if (ns.HandleReceive()) - { - count++; - } + ns.HandleReceive(); } - - return count; } public void Flush() @@ -995,13 +980,11 @@ namespace Server.Network } } - public static int Slice() + public static void Slice() { - int count = 0; while (FlushPending.Count != 0) { FlushPending.Dequeue()?.Flush(); - count++; } while (Disposed.TryDequeue(out var ns)) @@ -1009,8 +992,6 @@ namespace Server.Network TcpServer.Instances.Remove(ns); ns.Dispose(); } - - return count; } public void CheckAlive(long curTicks) diff --git a/Projects/Server/Network/TcpServer.cs b/Projects/Server/Network/TcpServer.cs index 7dcd9a962..06d7bd744 100644 --- a/Projects/Server/Network/TcpServer.cs +++ b/Projects/Server/Network/TcpServer.cs @@ -122,7 +122,7 @@ namespace Server.Network return null; } - public static int Slice() + public static void Slice() { int count = 0; @@ -132,8 +132,6 @@ namespace Server.Network ns.LogInfo("Connected. [{0} Online]", Instances.Count); ns.Start(); } - - return count; } private static async void BeginAcceptingSockets(this TcpListener listener) diff --git a/Projects/Server/Timer/Timer.TimerWheel.cs b/Projects/Server/Timer/Timer.TimerWheel.cs index b0bf65003..5389eb557 100644 --- a/Projects/Server/Timer/Timer.TimerWheel.cs +++ b/Projects/Server/Timer/Timer.TimerWheel.cs @@ -45,23 +45,19 @@ namespace Server } } - public static int Slice(long tickCount) + public static void Slice(long tickCount) { var deltaSinceTurn = tickCount - _lastTickTurned; - var events = 0; while (deltaSinceTurn >= _tickRate) { deltaSinceTurn -= _tickRate; _lastTickTurned += _tickRate; - events += Turn() ? 1 : 0; + Turn(); } - - return events; } - private static bool Turn() + private static void Turn() { - bool events = false; _timerWheelExecuting = true; var turnNextWheel = false; @@ -97,8 +93,6 @@ namespace Server continue; } - events = true; - do { var next = timer._nextTimer; @@ -124,8 +118,6 @@ namespace Server } _timerWheelExecuting = false; - - return events; } private static void Execute(Timer timer)