feat: Adds tidy option for serialization. Codegens ballotbox. Fixes pooled timer leaking (#681)

* Fixes pooled timer leaking
* Fixes `[dumptimers` command so it outputs properly, adds spacing, and stacktraces
* Adds `[Tidy]` for serializing Lists. This will remove deleted entities during world save before serializing the list.
* Adds helpers for managing Lists/Sets/Dictionaries


### New API

```cs
// Creates the list if it is null, then adds
Utility.Add(ref list, value);
Utility.Add(ref set, value);
Utility.Add(ref dict, key, value);

// Nulls the variable if the count is zero
Utility.Remove(ref list, value);
Utility.Remove(ref set, value);
Utility.Remove(ref dict, key);

// Marks entity as dirty in addition to doing the action
entity.Add(list, value);
// Marks entity as dirty, and will create list if it doesn't exist
entity.Add(ref list, value);

// Marks entity as dirty in addition to doing the action
entity.Remove(list, value);
// Marks entity as dirty, and will null the list count is zero
entity.Remove(ref list, value);
```


### Updates to [dumptimers
<img width="825" alt="Screen Shot 2021-08-14 at 2 55 10 AM" src="https://user-images.githubusercontent.com/3953314/129442449-ccf7fe14-29d6-4f3f-9366-c8eb7b9828a7.png">
This commit is contained in:
Kamron Batman 2021-08-14 03:02:53 -07:00 • committed by GitHub
parent 84cbd52a2a
commit 360143478a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 627 additions and 464 deletions

View file

@ -133,7 +133,7 @@ namespace Server
internal DelayCallTimer(TimeSpan delay) : base(delay)
{
#if DEBUG_TIMERS
t._allowFinalization = true;
_allowFinalization = true;
#endif
Start();
}
@ -164,12 +164,15 @@ namespace Server
Version++; // Increment the version so if this is called from OnTick() and another timer is started, we don't have a problem
#if DEBUG_TIMERS
_stackTraces.Remove(GetHashCode());
#endif
if (_poolCount >= _poolCapacity)
{
#if DEBUG_TIMERS
logger.Warning($"DelayCallTimer pool reached maximum of {_poolSize} timers");
logger.Warning($"DelayCallTimer pool reached maximum of {_poolCapacity} timers");
_allowFinalization = true;
_stackTraces.Remove(GetHashCode());
#endif
return;
}
@ -184,7 +187,7 @@ namespace Server
{
_poolCount--;
#if DEBUG_TIMERS
logger.Information($"Pool count changed: {_poolCount} ({_poolCapacity})");
logger.Information($"Pool count: {_poolCount} / {_poolCapacity}");
#endif
var timer = GetFromPool();
@ -202,7 +205,7 @@ namespace Server
_timerPoolDepletionAmount++;
#if DEBUG_TIMERS
logger.Warning($"Timer pool depleted and timer was allocated.\n{new StackTrace()});
logger.Warning($"Timer pool depleted and timer was allocated.\n{new StackTrace()}");
#endif
return new DelayCallTimer(delay, interval, count, callback);
}

View file

@ -62,7 +62,7 @@ namespace Server
_poolHead = head;
_poolCount += amount;
#if DEBUG_TIMERS
logger.Information($"Pool count changed: {_poolCount} ({_poolCapacity})");
logger.Information($"Pool count: {_poolCount} / {_poolCapacity}");
#endif
}

View file

@ -203,9 +203,7 @@ namespace Server
public static void DumpInfo(TextWriter tw)
{
var now = DateTime.UtcNow;
tw.WriteLine("Date: {0}\n", now);
tw.WriteLine("Date: {0}\n", Core.Now.ToLocalTime());
tw.WriteLine("Pool - Count: {0}; Size {1}\n", _poolCount - _timerPoolDepletionAmount, _poolCapacity);
var total = 0.0;
@ -216,6 +214,10 @@ namespace Server
for (var j = 0; j < _ringSize; j++)
{
var t = _rings[i][j];
if (t == null)
{
continue;
}
var name = t.ToString();
@ -230,9 +232,22 @@ namespace Server
foreach (var (name, count) in hash.OrderByDescending(o => o.Value))
{
tw.WriteLine($"- Type: {name}; Count: {count}; Percent: {count / total}%");
var percent = count / total;
var line = $"{count:#,0} ({percent:P1})";
// 6 - 15 / 8 = 1
var tabs = new string('\t', line.Length < 12 ? 2 : 1);
tw.WriteLine($"{line}{tabs}{name}");
}
#if DEBUG_TIMERS
tw.WriteLine("\nStack Traces:");
foreach (var kvp in DelayCallTimer._stackTraces)
{
tw.WriteLine(kvp.Value);
tw.WriteLine();
}
#endif
tw.WriteLine();
tw.WriteLine();
}