Created
April 16, 2017 00:28
-
-
Save Brian1KB/7006dfb938cf5ae8451f3bb0224d9cea to your computer and use it in GitHub Desktop.
High Precision Timer V1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Threading; | |
using log4net; | |
namespace MiNET.Utils | |
{ | |
public class HighPrecisionTimer : IDisposable | |
{ | |
private static readonly ILog Log = LogManager.GetLogger(typeof (HighPrecisionTimer)); | |
private static readonly DedicatedThreadPool ThreadPool = | |
new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount)); | |
private static readonly List<HighPrecisionTimer> Timers = new List<HighPrecisionTimer>(); | |
private static readonly Stopwatch Stopwatch = new Stopwatch(); | |
private static readonly object TimersLock = new object(); | |
private static bool _shouldClose; | |
private readonly Action<object> _action; | |
private readonly int _interval; | |
private long _nextStop; | |
private long _queueTime; | |
static HighPrecisionTimer() | |
{ | |
Stopwatch.Start(); | |
var thread = new Thread(() => | |
{ | |
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; | |
Thread.CurrentThread.Name = "High Precision Timer Ticker"; | |
var completedTickTime = Stopwatch.ElapsedMilliseconds; | |
while (!_shouldClose) | |
{ | |
var timeSinceLastTick = Stopwatch.ElapsedMilliseconds - completedTickTime; | |
if (timeSinceLastTick > 15) Log.Warn($"{timeSinceLastTick}ms since last tick!"); | |
HighPrecisionTimer[] timers; | |
lock (TimersLock) | |
{ | |
timers = Timers.ToArray(); | |
} | |
foreach (var timer in timers) | |
{ | |
if (Stopwatch.ElapsedMilliseconds < timer._nextStop) continue; | |
timer._nextStop = Stopwatch.ElapsedMilliseconds + 1000*60; | |
timer._queueTime = Stopwatch.ElapsedMilliseconds; | |
var stopwatch = new Stopwatch(); | |
stopwatch.Start(); | |
ThreadPool.QueueUserWorkItem(() => | |
{ | |
var queueTime = Stopwatch.ElapsedMilliseconds - timer._queueTime; | |
if (queueTime > 10) Log.Warn($"Queue took {queueTime}ms to execute action!"); | |
try | |
{ | |
timer._action.Invoke(timer); | |
} | |
catch (Exception e) | |
{ | |
Log.Error("Exception while processing precision action: ", e); | |
} | |
finally | |
{ | |
timer._nextStop = Stopwatch.ElapsedMilliseconds + timer._interval; | |
} | |
}); | |
stopwatch.Stop(); | |
if (stopwatch.ElapsedMilliseconds > 5) | |
Log.Warn($"Took {stopwatch.ElapsedMilliseconds}ms to add action to queue!"); | |
} | |
completedTickTime = Stopwatch.ElapsedMilliseconds; | |
Thread.Yield(); | |
} | |
}); | |
thread.Start(); | |
} | |
public HighPrecisionTimer(int interval, Action<object> action) | |
{ | |
_action = action; | |
_interval = interval; | |
_nextStop = Stopwatch.ElapsedMilliseconds + interval; | |
lock (TimersLock) | |
{ | |
Timers.Add(this); | |
} | |
} | |
public void Dispose() | |
{ | |
lock (TimersLock) | |
{ | |
Timers.Remove(this); | |
} | |
} | |
public static void Close() | |
{ | |
_shouldClose = true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment