fix(core): Caches DateTime.NowUtc (#548)

- [X] Caches DateTime.NowUtc on the game loop (not other threads)
- [X] Replaces all locations where it makes sense
- [X] Adds Min/Max for `IComparable` (TimeSpan, DateTimes, etc)

Closes #261
This commit is contained in:
Kamron Batman 2021-03-13 01:32:04 -08:00 committed by GitHub
parent 5de6edbeb8
commit 6c4308bce6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
208 changed files with 660 additions and 793 deletions

View file

@ -955,7 +955,7 @@ namespace Server
/* begin last moved time optimization */
var ticks = LastMoved.Ticks;
var now = DateTime.UtcNow.Ticks;
var now = Core.Now.Ticks;
var minutes = new TimeSpan(now - ticks).TotalMinutes;
@ -2280,7 +2280,7 @@ namespace Server
public void SetLastMoved()
{
LastMoved = DateTime.UtcNow;
LastMoved = Core.Now;
}
public virtual bool CanStackWith(Item dropped) =>
@ -2598,11 +2598,11 @@ namespace Server
try
{
LastMoved = DateTime.UtcNow - TimeSpan.FromMinutes(minutes);
LastMoved = Core.Now - TimeSpan.FromMinutes(minutes);
}
catch
{
LastMoved = DateTime.UtcNow;
LastMoved = Core.Now;
}
}

View file

@ -37,8 +37,8 @@ namespace Server
private static string _baseDirectory;
private static bool _profiling;
private static DateTime _profileStart;
private static TimeSpan _profileTime;
private static long _profileStart;
private static long _profileTime;
#nullable enable
private static bool? _isRunningFromXUnit;
#nullable restore
@ -95,19 +95,17 @@ namespace Server
_profiling = value;
if (_profileStart > DateTime.MinValue)
if (_profileStart > 0)
{
_profileTime += DateTime.UtcNow - _profileStart;
_profileTime += TickCount - _profileStart;
}
_profileStart = _profiling ? DateTime.UtcNow : DateTime.MinValue;
_profileStart = _profiling ? TickCount : 0;
}
}
public static TimeSpan ProfileTime =>
_profileStart > DateTime.MinValue
? _profileTime + (DateTime.UtcNow - _profileStart)
: _profileTime;
TimeSpan.FromMilliseconds(_profileStart > 0 ? _profileTime + (TickCount - _profileStart) : _profileTime);
public static Assembly Assembly { get; set; }
@ -118,7 +116,11 @@ namespace Server
public static Thread Thread { get; private set; }
[ThreadStatic] private static long _tickCount;
[ThreadStatic]
private static long _tickCount;
[ThreadStatic]
private static DateTime _now;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static long GetTicks() => 1000L * Stopwatch.GetTimestamp() / Stopwatch.Frequency;
@ -129,6 +131,12 @@ namespace Server
set => _tickCount = value;
}
public static DateTime Now
{
get => _now == DateTime.MinValue ? DateTime.UtcNow : _now;
set => _now = value;
}
public static bool MultiProcessor { get; private set; }
public static int ProcessorCount { get; private set; }
@ -488,6 +496,7 @@ namespace Server
while (!Closing)
{
_tickCount = TickCount;
_now = DateTime.UtcNow;
var events = Mobile.ProcessDeltaQueue();
events += Item.ProcessDeltaQueue();
@ -502,6 +511,7 @@ namespace Server
events += _eventLoopContext.ExecuteTasks();
_tickCount = 0;
_now = DateTime.MinValue;
if (events > 0)
{

View file

@ -38,7 +38,7 @@ namespace Server
DumpAccess();
}
return m_Attacker.Deleted || m_Defender.Deleted || DateTime.UtcNow >= m_LastCombatTime + ExpireDelay;
return m_Attacker.Deleted || m_Defender.Deleted || Core.Now >= m_LastCombatTime + ExpireDelay;
}
}
@ -200,7 +200,7 @@ namespace Server
DumpAccess();
}
m_LastCombatTime = DateTime.UtcNow;
m_LastCombatTime = Core.Now;
m_Reported = false;
}
}

View file

@ -34,7 +34,7 @@ namespace Server
private readonly DateTime m_Expire;
public TimedSkillMod(SkillName skill, bool relative, double value, TimeSpan delay)
: this(skill, relative, value, DateTime.UtcNow + delay)
: this(skill, relative, value, Core.Now + delay)
{
}
@ -42,7 +42,7 @@ namespace Server
: base(skill, relative, value) =>
m_Expire = expire;
public override bool CheckCondition() => DateTime.UtcNow < m_Expire;
public override bool CheckCondition() => Core.Now < m_Expire;
}
public class EquippedSkillMod : SkillMod
@ -240,7 +240,7 @@ namespace Server
Name = name;
Offset = offset;
m_Duration = duration;
m_Added = DateTime.UtcNow;
m_Added = Core.Now;
}
public StatType Type { get; }
@ -249,15 +249,7 @@ namespace Server
public int Offset { get; }
public bool HasElapsed()
{
if (m_Duration == TimeSpan.Zero)
{
return false;
}
return DateTime.UtcNow - m_Added >= m_Duration;
}
public bool HasElapsed() => m_Duration != TimeSpan.Zero && Core.Now - m_Added >= m_Duration;
}
public class DamageEntry
@ -270,7 +262,7 @@ namespace Server
public DateTime LastDamage { get; set; }
public bool HasExpired => DateTime.UtcNow > LastDamage + ExpireDelay;
public bool HasExpired => Core.Now > LastDamage + ExpireDelay;
public List<DamageEntry> Responsible { get; set; }
@ -3747,7 +3739,7 @@ namespace Server
return;
}
var now = DateTime.UtcNow;
var now = Core.Now;
var next = m_NextWarmodeChange;
if (now > next || m_WarmodeChanges == 0)
@ -5996,7 +5988,7 @@ namespace Server
var de = FindDamageEntryFor(from) ?? new DamageEntry(from);
de.DamageGiven += amount;
de.LastDamage = DateTime.UtcNow;
de.LastDamage = Core.Now;
DamageEntries.Remove(de);
DamageEntries.Add(de);
@ -6028,7 +6020,7 @@ namespace Server
}
resp.DamageGiven += amount;
resp.LastDamage = DateTime.UtcNow;
resp.LastDamage = Core.Now;
}
return de;
@ -7925,7 +7917,7 @@ namespace Server
DamageEntries = new List<DamageEntry>();
NextSkillTime = Core.TickCount;
CreationTime = DateTime.UtcNow;
CreationTime = Core.Now;
}
public virtual void Delta(MobileDelta flag)

View file

@ -148,14 +148,14 @@ namespace Server.Network
_toString = "(error)";
}
ConnectedOn = DateTime.UtcNow;
ConnectedOn = Core.Now;
CreatedCallback?.Invoke(this);
}
public DateTime ConnectedOn { get; }
public TimeSpan ConnectedFor => DateTime.UtcNow - ConnectedOn;
public TimeSpan ConnectedFor => Core.Now - ConnectedOn;
public IPAddress Address { get; }
@ -1034,7 +1034,7 @@ namespace Server.Network
try
{
using var op = new StreamWriter("network-errors.log", true);
op.WriteLine("# {0}", DateTime.UtcNow);
op.WriteLine("# {0}", Core.Now);
op.WriteLine(ex);
@ -1083,7 +1083,7 @@ namespace Server.Network
try
{
using StreamWriter op = new StreamWriter("network-disconnects.log", true);
op.WriteLine($"# {DateTime.UtcNow}");
op.WriteLine($"# {Core.Now}");
op.WriteLine($"NetState: {ip}");
op.WriteLine(reason);

View file

@ -33,7 +33,7 @@ namespace Server.Network
public AuthIDPersistence(ClientVersion v)
{
Age = DateTime.UtcNow;
Age = Core.Now;
Version = v;
}
}

View file

@ -326,9 +326,8 @@ namespace Server.Network
ns.Send(writer.Span);
}
// TODO: Use DateTime caching against core loop
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendCurrentTime(this NetState ns) => ns.SendCurrentTime(DateTime.UtcNow);
public static void SendCurrentTime(this NetState ns) => ns.SendCurrentTime(Core.Now);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendCurrentTime(this NetState ns, DateTime date) =>

View file

@ -205,6 +205,8 @@ namespace Server
Write(ticks);
}
// TODO: Find a way to speed this up.
// Maybe used a special cached value?
public void WriteDeltaTime(DateTime value)
{
var ticks = (value.Kind switch

View file

@ -84,14 +84,14 @@ namespace Server
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteConsole(string message)
{
var now = DateTime.UtcNow;
var now = Core.Now;
Console.Write("[{0} {1}] Persistence: {2}", now.ToShortDateString(), now.ToLongTimeString(), message);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteConsoleLine(string message)
{
var now = DateTime.UtcNow;
var now = Core.Now;
Console.WriteLine("[{0} {1}] Persistence: {2}", now.ToShortDateString(), now.ToLongTimeString(), message);
}
@ -100,7 +100,7 @@ namespace Server
try
{
using var op = new StreamWriter("save-errors.log", true);
op.WriteLine("# {0}", DateTime.UtcNow);
op.WriteLine("# {0}", Core.Now);
op.WriteLine(ex);

View file

@ -19,7 +19,7 @@ namespace Server.Targeting
CheckLOS = true;
}
public DateTime TimeoutTime { get; private set; }
public long TimeoutTime { get; private set; }
public bool CheckLOS { get; set; }
@ -41,13 +41,13 @@ namespace Server.Targeting
m.Target?.OnTargetCancel(m, TargetCancelType.Canceled);
}
public void BeginTimeout(Mobile from, TimeSpan delay)
public void BeginTimeout(Mobile from, long delay)
{
TimeoutTime = DateTime.UtcNow + delay;
TimeoutTime = Core.TickCount + delay;
m_TimeoutTimer?.Stop();
m_TimeoutTimer = new TimeoutTimer(this, from, delay);
m_TimeoutTimer = new TimeoutTimer(this, from, TimeSpan.FromMilliseconds(delay));
m_TimeoutTimer.Start();
}

View file

@ -390,10 +390,10 @@ namespace Server
}
catch (EndOfStreamException ex)
{
if (DateTime.UtcNow >= m_NextStaticWarning)
if (Core.Now >= m_NextStaticWarning)
{
Console.WriteLine("Warning: Static EOS for {0} ({1}, {2})", _map, x, y);
m_NextStaticWarning = DateTime.UtcNow + TimeSpan.FromMinutes(1.0);
m_NextStaticWarning = Core.Now + TimeSpan.FromMinutes(1.0);
}
return _emptyStaticBlock;
@ -438,10 +438,10 @@ namespace Server
}
catch (Exception ex)
{
if (DateTime.UtcNow >= m_NextLandWarning)
if (Core.Now >= m_NextLandWarning)
{
Console.WriteLine("Warning: Land EOS for {0} ({1}, {2})", _map, x, y);
m_NextLandWarning = DateTime.UtcNow + TimeSpan.FromMinutes(1.0);
m_NextLandWarning = Core.Now + TimeSpan.FromMinutes(1.0);
}
return _invalidLandBlock;

View file

@ -1338,7 +1338,10 @@ namespace Server
val.CompareTo(max) > 0 ? max : val;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TimeSpan Max(this TimeSpan val, TimeSpan max) => val > max ? max : val;
public static T Min<T>(T val, T min) where T : IComparable<T> => val.CompareTo(min) < 0 ? val : min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Max<T>(T val, T max) where T : IComparable<T> => val.CompareTo(max) > 0 ? val : max;
public static string TrimMultiline(this string str, string lineSeparator = "\n")
{
@ -1434,6 +1437,6 @@ namespace Server
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetTimeStamp() => DateTime.UtcNow.ToString("yyyy-MM-dd-HH-mm-ss");
public static string GetTimeStamp() => Core.Now.ToString("yyyy-MM-dd-HH-mm-ss");
}
}