From edea1d4906f403f5769035b46a339f855775ab50 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 13 May 2021 18:22:42 -0700 Subject: [PATCH] fix(core): Fixes core tick count for VMs (#600) Some architectures (specifically docker) have an issue with tick count and high precision timing. This handles those weird cases so instead of outright freezing, you may get timer precision loss. --- Projects/Server/Main.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Projects/Server/Main.cs b/Projects/Server/Main.cs index 15e7732e0..0612de954 100644 --- a/Projects/Server/Main.cs +++ b/Projects/Server/Main.cs @@ -125,12 +125,26 @@ namespace Server [ThreadStatic] private static DateTime _now; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static long GetTicks() => 1000L * Stopwatch.GetTimestamp() / Stopwatch.Frequency; + // For Unix Stopwatch.Frequency is normalized to 1ns + // We don't anticipate needing this for Windows/OSX + private static long _maxTickCountBeforePrecisionLoss = long.MaxValue / 1000L; + private static long _ticksPerMillisecond = Stopwatch.Frequency / 1000L; public static long TickCount { - get => _tickCount == 0 ? GetTicks() : _tickCount; + get + { + if (_tickCount != 0) + { + return _tickCount; + } + + var timestamp = Stopwatch.GetTimestamp(); + return timestamp > _maxTickCountBeforePrecisionLoss + ? timestamp / _ticksPerMillisecond + // No precision loss + : 1000L * timestamp / Stopwatch.Frequency; + } set => _tickCount = value; }