Esempio n. 1
0
        public HighPrecisionTimer(int interval)
        {
            log.Info("Starting HighPrecisionTimer with" + interval.ToString() + " ms interval");

            if (interval < 1)
            {
                throw new ArgumentOutOfRangeException();
            }
            System.Diagnostics.Trace.Assert(interval >= 10, "Not reliable/tested, may use too much CPU");

            cancelSource = new CancellationTokenSource();

            // Used to report timing accuracy for 1 sec, running total
            tickTiming = new CircularBuffer.CircularBuffer <int>(1000 / interval, true);

            var  watch      = System.Diagnostics.Stopwatch.StartNew();
            long durationMs = 0;
            long totalTicks = 0;
            long nextStop   = interval;
            long lastReport = 0;

            var task = new Task(() =>
            {
                while (!this.cancelSource.IsCancellationRequested)
                {
                    long msLeft = nextStop - watch.ElapsedMilliseconds;
                    if (msLeft <= 0)
                    {
                        durationMs = watch.ElapsedMilliseconds;
                        totalTicks = durationMs / interval;

                        tickTiming.Put((int)(durationMs - nextStop));

                        if (durationMs - lastReport >= 1000)
                        {
                            // Report
                            log.Debug(string.Concat("Last second - avg: {0:F1}  best: {1}  worst: {2}",
                                                    tickTiming.Average(), tickTiming.Min(), tickTiming.Max()));

                            lastReport = durationMs;
                        }

                        var handler = Tick;
                        if (handler != null)
                        {
                            handler(this, new TickEventArgs(TimeSpan.FromMilliseconds(durationMs), totalTicks));
                        }

                        // Calculate when the next stop is. If we're too slow on the trigger then we'll skip ticks
                        nextStop = interval * (watch.ElapsedMilliseconds / interval + 1);
                    }
                    else if (msLeft < 16)
                    {
                        System.Threading.SpinWait.SpinUntil(() => watch.ElapsedMilliseconds >= nextStop);
                        continue;
                    }

                    System.Threading.Thread.Sleep(1);
                }
            }, cancelSource.Token, TaskCreationOptions.LongRunning);

            task.Start();
        }
Esempio n. 2
0
        public HighPrecisionTimer(int intervalMs, bool startRunning = true)
        {
            log.Info("Starting HighPrecisionTimer with {0} ms interval", intervalMs);

            if (intervalMs < 1)
                throw new ArgumentOutOfRangeException();
            System.Diagnostics.Trace.Assert(intervalMs >= 10, "Not reliable/tested, may use too much CPU");

            this.IntervalMs = intervalMs;
            this.cancelSource = new CancellationTokenSource();
            this.taskComplete = new ManualResetEvent(false);

            #if PROFILE
            // Used to report timing accuracy for 1 sec, running total
            tickTiming = new CircularBuffer.CircularBuffer<int>(1000 / intervalMs, true);
            execTiming = new CircularBuffer.CircularBuffer<long>(1000 / intervalMs, true);
            #endif

            var watch = System.Diagnostics.Stopwatch.StartNew();
            long durationMs = 0;
            long totalTicks = 0;
            long nextStop = intervalMs;
            #if PROFILE
            long lastReport = 0;
            #endif

            this.task = new Task(() =>
                {
                    var eventArgs = new TickEventArgs();

                    while (!this.cancelSource.IsCancellationRequested)
                    {
                        long msLeft = nextStop - watch.ElapsedMilliseconds;
                        if (msLeft <= 0)
                        {
                            durationMs = watch.ElapsedMilliseconds;
                            totalTicks = durationMs / intervalMs;

            #if PROFILE
                            var execWatch = System.Diagnostics.Stopwatch.StartNew();
            #endif
                            var handler = Tick;
                            if (handler != null)
                            {
                                eventArgs.Duration = TimeSpan.FromMilliseconds(durationMs);
                                eventArgs.TotalTicks = totalTicks;
                                handler(this, eventArgs);
                                if (eventArgs.Cancel)
                                    break;
                            }
            #if PROFILE
                            execWatch.Stop();
                            execTiming.Put(execWatch.ElapsedTicks);
                            tickTiming.Put((int)(durationMs - nextStop));

                            if (durationMs - lastReport >= 1000)
                            {
                                // Report
                                log.Debug("HighPTimer  avg: {0:F1}  best: {1}  worst: {2}   MaxExec: {3:N1}ms",
                                    tickTiming.Average(), tickTiming.Min(), tickTiming.Max(),
                                    TimeSpan.FromTicks(execTiming.Max()).TotalMilliseconds);

                                lastReport = durationMs;
                            }
            #endif

                            // Calculate when the next stop is. If we're too slow on the trigger then we'll skip ticks
                            nextStop = intervalMs * (watch.ElapsedMilliseconds / intervalMs + 1);
                            continue;
                        }
                        else if (msLeft < 16)
                        {
                            System.Threading.SpinWait.SpinUntil(() => watch.ElapsedMilliseconds >= nextStop);
                            continue;
                        }

                        System.Threading.Thread.Sleep(1);
                    }

                    this.taskComplete.Set();
                }, cancelSource.Token, TaskCreationOptions.LongRunning);

            if (startRunning)
                this.task.Start();
        }
Esempio n. 3
0
        public HighPrecisionTimer2(int intervalMs, bool startRunning = true)
        {
            this.log = Log.Logger;
            this.log.Information("Starting HighPrecisionTimer2 with {0} ms interval", intervalMs);

            this.outputValue = new Subject <long>();

            if (intervalMs < 1)
            {
                throw new ArgumentOutOfRangeException();
            }
            System.Diagnostics.Trace.Assert(intervalMs >= 10, "Not reliable/tested, may use too much CPU");

            this.IntervalMs   = intervalMs;
            this.cancelSource = new CancellationTokenSource();
            this.taskComplete = new ManualResetEvent(false);

#if PROFILE
            // Used to report timing accuracy for 1 sec, running total
            tickTiming = new CircularBuffer.CircularBuffer <int>(1000 / intervalMs, true);
            execTiming = new CircularBuffer.CircularBuffer <long>(1000 / intervalMs, true);
#endif

            watch = System.Diagnostics.Stopwatch.StartNew();
            long durationMs = 0;
            long nextStop   = intervalMs;
#if PROFILE
            long lastReport = 0;
#endif

            this.task = new Task(() =>
            {
                while (!this.cancelSource.IsCancellationRequested)
                {
                    long msLeft = nextStop - watch.ElapsedMilliseconds;
                    if (msLeft <= 0)
                    {
                        durationMs = watch.ElapsedMilliseconds;

#if PROFILE
                        var execWatch = System.Diagnostics.Stopwatch.StartNew();
#endif
                        this.outputValue.OnNext(durationMs);

#if PROFILE
                        execWatch.Stop();
                        execTiming.Put(execWatch.ElapsedTicks);
                        tickTiming.Put((int)(durationMs - nextStop));

                        if (durationMs - lastReport >= 1000)
                        {
                            // Report
                            log.Debug("HighPTimer  avg: {0:F1}  best: {1}  worst: {2}   MaxExec: {3:N1}ms",
                                      tickTiming.Average(), tickTiming.Min(), tickTiming.Max(),
                                      TimeSpan.FromTicks(execTiming.Max()).TotalMilliseconds);

                            lastReport = durationMs;
                        }
#endif

                        // Calculate when the next stop is. If we're too slow on the trigger then we'll skip ticks
                        nextStop = intervalMs * (watch.ElapsedMilliseconds / intervalMs + 1);
                        continue;
                    }
                    else if (msLeft < 16)
                    {
                        System.Threading.SpinWait.SpinUntil(() => watch.ElapsedMilliseconds >= nextStop);
                        continue;
                    }

                    System.Threading.Thread.Sleep(1);
                }

                this.taskComplete.Set();
            }, cancelSource.Token, TaskCreationOptions.LongRunning);

            if (startRunning)
            {
                this.task.Start();
            }
        }