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
This commit is contained in:
Kamron Batman 2021-09-17 00:15:16 -07:00 committed by GitHub
parent b6641c4853
commit 56c348ac68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 80 deletions

View file

@ -55,7 +55,7 @@ namespace Server
evt.WaitOne(); evt.WaitOne();
} }
public int ExecuteTasks() public void ExecuteTasks()
{ {
if (Thread.CurrentThread != _mainThread) if (Thread.CurrentThread != _mainThread)
{ {
@ -66,15 +66,11 @@ namespace Server
for (int i = 0; i < count; i++) 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;
} }
} }
} }

View file

@ -3249,10 +3249,8 @@ namespace Server
m_DeltaFlags &= ~flags; m_DeltaFlags &= ~flags;
} }
public static int ProcessDeltaQueue() public static void ProcessDeltaQueue()
{ {
int count = 0;
var limit = m_DeltaQueue.Count; var limit = m_DeltaQueue.Count;
while (m_DeltaQueue.Count > 0 && --limit >= 0) while (m_DeltaQueue.Count > 0 && --limit >= 0)
@ -3264,8 +3262,6 @@ namespace Server
continue; continue;
} }
count++;
item.SetFlag(ImplFlag.InQueue, false); item.SetFlag(ImplFlag.InQueue, false);
try try
@ -3286,8 +3282,6 @@ namespace Server
Console.WriteLine("Warning: {0} items left in delta queue after processing.", m_DeltaQueue.Count); Console.WriteLine("Warning: {0} items left in delta queue after processing.", m_DeltaQueue.Count);
Utility.PopColor(); Utility.PopColor();
} }
return count;
} }
public virtual void OnDelete() public virtual void OnDelete()

View file

@ -155,6 +155,11 @@ namespace Server
set => _now = value; 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 bool MultiProcessor { get; private set; }
public static int ProcessorCount { get; private set; } public static int ProcessorCount { get; private set; }
@ -488,40 +493,52 @@ namespace Server
{ {
try try
{ {
#if DEBUG
var idleCPU = true;
#else
var idleCPU = ServerConfiguration.GetOrUpdateSetting("core.enableIdleCPU", false);
#endif
long last = TickCount;
const int interval = 100; const int interval = 100;
int idleCount = 0; const float ticksPerSecond = 1000 * interval;
int sample = 0;
while (!Closing) while (!Closing)
{ {
_tickCount = TickCount; _tickCount = TickCount;
_now = DateTime.UtcNow; _now = DateTime.UtcNow;
var events = Mobile.ProcessDeltaQueue(); Mobile.ProcessDeltaQueue();
events += Item.ProcessDeltaQueue(); Item.ProcessDeltaQueue();
events += Timer.Slice(_tickCount); Timer.Slice(_tickCount);
// Handle networking // Handle networking
events += TcpServer.Slice(); TcpServer.Slice();
events += NetState.HandleAllReceives(); NetState.HandleAllReceives();
events += NetState.Slice(); NetState.Slice();
// Execute captured post-await methods (like Timer.Pause) // 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. Timer.CheckTimerPool(); // Check for pool depletion so we can async refill it.
_tickCount = 0; _tickCount = 0;
_now = DateTime.MinValue; _now = DateTime.MinValue;
if (events > 0) if (idleCPU && ++sample % interval == 0)
{ {
idleCount = 0; var now = TickCount;
continue;
}
if (++idleCount > interval) var cyclesPerSecond = ticksPerSecond / (now - last);
{ _cyclesPerSecond[_cycleIndex++ % _cyclesPerSecond.Length] = cyclesPerSecond;
Thread.Sleep(1); last = now;
if (cyclesPerSecond > 80)
{
Thread.Sleep(2);
}
} }
} }
} }

View file

@ -7848,10 +7848,8 @@ namespace Server
} }
} }
public static int ProcessDeltaQueue() public static void ProcessDeltaQueue()
{ {
int count = 0;
var limit = m_DeltaQueue.Count; var limit = m_DeltaQueue.Count;
while (m_DeltaQueue.Count > 0 && --limit >= 0) while (m_DeltaQueue.Count > 0 && --limit >= 0)
@ -7863,8 +7861,6 @@ namespace Server
continue; continue;
} }
count++;
mob.m_InDeltaQueue = false; mob.m_InDeltaQueue = false;
try try
@ -7885,8 +7881,6 @@ namespace Server
Console.WriteLine("Warning: {0} mobiles left in delta queue after processing.", m_DeltaQueue.Count); Console.WriteLine("Warning: {0} mobiles left in delta queue after processing.", m_DeltaQueue.Count);
Utility.PopColor(); Utility.PopColor();
} }
return count;
} }
public virtual void OnKillsChange(int oldValue) public virtual void OnKillsChange(int oldValue)

View file

@ -538,16 +538,13 @@ namespace Server.Network
ThreadPool.UnsafeQueueUserWorkItem(SendTask, null); ThreadPool.UnsafeQueueUserWorkItem(SendTask, null);
} }
// Return true if there was any data to be processed. False otherwise. Used for idle detection. public void HandleReceive()
public bool HandleReceive()
{ {
if (!Running) if (!Running)
{ {
return false; return;
} }
bool active = false;
var reader = RecvPipe.Reader; var reader = RecvPipe.Reader;
try try
@ -563,9 +560,6 @@ namespace Server.Network
break; break;
} }
// There was at least some data found, so it's not idle.
active = true;
var packetReader = new CircularBufferReader(result.Buffer); var packetReader = new CircularBufferReader(result.Buffer);
var packetId = packetReader.ReadByte(); var packetId = packetReader.ReadByte();
int packetLength = length; int packetLength = length;
@ -583,7 +577,7 @@ namespace Server.Network
case ProtocolState.Uninitialized: case ProtocolState.Uninitialized:
{ {
HandleError(packetId, packetLength); HandleError(packetId, packetLength);
return true; return;
} }
case ProtocolState.AwaitingSeed: case ProtocolState.AwaitingSeed:
@ -604,7 +598,7 @@ namespace Server.Network
if (seed == 0) if (seed == 0)
{ {
HandleError(0, 0); HandleError(0, 0);
return true; return;
} }
_seed = seed; _seed = seed;
@ -626,7 +620,7 @@ namespace Server.Network
{ {
LogInfo("Possible encrypted client detected, disconnecting..."); LogInfo("Possible encrypted client detected, disconnecting...");
HandleError(packetId, packetLength); HandleError(packetId, packetLength);
return true; return;
} }
_parserState = ParserState.ProcessingPacket; _parserState = ParserState.ProcessingPacket;
@ -643,7 +637,7 @@ namespace Server.Network
if (packetId != 0xA0) if (packetId != 0xA0)
{ {
HandleError(packetId, packetLength); HandleError(packetId, packetLength);
return true; return;
} }
_parserState = ParserState.ProcessingPacket; _parserState = ParserState.ProcessingPacket;
@ -665,7 +659,7 @@ namespace Server.Network
_parserState = ParserState.AwaitingNextPacket; _parserState = ParserState.AwaitingNextPacket;
_protocolState = ProtocolState.AwaitingSeed; _protocolState = ProtocolState.AwaitingSeed;
#endif #endif
return true; return;
} }
case ProtocolState.GameServer_AwaitingGameServerLogin: case ProtocolState.GameServer_AwaitingGameServerLogin:
@ -673,7 +667,7 @@ namespace Server.Network
if (packetId != 0x91 && packetId != 0x80) if (packetId != 0x91 && packetId != 0x80)
{ {
HandleError(packetId, packetLength); HandleError(packetId, packetLength);
return true; return;
} }
_parserState = ParserState.ProcessingPacket; _parserState = ParserState.ProcessingPacket;
@ -719,8 +713,6 @@ namespace Server.Network
TraceException(ex); TraceException(ex);
Disconnect("Exception during HandleReceive"); Disconnect("Exception during HandleReceive");
} }
return active;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [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) foreach (var ns in TcpServer.Instances)
{ {
if (ns.HandleReceive()) ns.HandleReceive();
{
count++;
}
} }
return count;
} }
public void Flush() 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) while (FlushPending.Count != 0)
{ {
FlushPending.Dequeue()?.Flush(); FlushPending.Dequeue()?.Flush();
count++;
} }
while (Disposed.TryDequeue(out var ns)) while (Disposed.TryDequeue(out var ns))
@ -1009,8 +992,6 @@ namespace Server.Network
TcpServer.Instances.Remove(ns); TcpServer.Instances.Remove(ns);
ns.Dispose(); ns.Dispose();
} }
return count;
} }
public void CheckAlive(long curTicks) public void CheckAlive(long curTicks)

View file

@ -122,7 +122,7 @@ namespace Server.Network
return null; return null;
} }
public static int Slice() public static void Slice()
{ {
int count = 0; int count = 0;
@ -132,8 +132,6 @@ namespace Server.Network
ns.LogInfo("Connected. [{0} Online]", Instances.Count); ns.LogInfo("Connected. [{0} Online]", Instances.Count);
ns.Start(); ns.Start();
} }
return count;
} }
private static async void BeginAcceptingSockets(this TcpListener listener) private static async void BeginAcceptingSockets(this TcpListener listener)

View file

@ -45,23 +45,19 @@ namespace Server
} }
} }
public static int Slice(long tickCount) public static void Slice(long tickCount)
{ {
var deltaSinceTurn = tickCount - _lastTickTurned; var deltaSinceTurn = tickCount - _lastTickTurned;
var events = 0;
while (deltaSinceTurn >= _tickRate) while (deltaSinceTurn >= _tickRate)
{ {
deltaSinceTurn -= _tickRate; deltaSinceTurn -= _tickRate;
_lastTickTurned += _tickRate; _lastTickTurned += _tickRate;
events += Turn() ? 1 : 0; Turn();
} }
return events;
} }
private static bool Turn() private static void Turn()
{ {
bool events = false;
_timerWheelExecuting = true; _timerWheelExecuting = true;
var turnNextWheel = false; var turnNextWheel = false;
@ -97,8 +93,6 @@ namespace Server
continue; continue;
} }
events = true;
do do
{ {
var next = timer._nextTimer; var next = timer._nextTimer;
@ -124,8 +118,6 @@ namespace Server
} }
_timerWheelExecuting = false; _timerWheelExecuting = false;
return events;
} }
private static void Execute(Timer timer) private static void Execute(Timer timer)