/// <summary> /// This gives an accurate estimate of DateTime from ticks over shorter intervals, it won't be accurate over really long intervals though /// </summary> DateTime PerfCounterRawDateTime() { long result; Startwatch.QueryPerformanceCounter(out result); return(DateTime.Now.AddSeconds(-result / Stopwatch.Frequency)); }
/// <summary> /// Create the advancement function which will generate the sequence of timers. /// Calling this function will automatically close the entire timer hierarchy. /// After calling this function, the modeller will become invalidated /// and no other functionality will be available. /// </summary> /// <para> /// The first call to the advancement function will start the timer modelling /// hierarchy, and each subsequent call will stop the previously returned timer, /// and return the next one. The advancement function will eventually /// reach the end of the modelled hierarchy, at which point it will /// return the <see cref="TotalTimer" /> on each call. It is up /// to the caller to stop the TotalTimer at the appropriate point, /// which may either be immediately upon seeing it or /// at some final point later in the timer hierarchy. /// </para> public Func <Startwatch> CreateAdvancementFunction() { if (_current == null) { throw new InvalidModellerStateException(); } while (_parents.Count > 1) { Pop(); } _current = null; var enum1 = _tracking.GetEnumerator(); if (_tracking[0] != BeforeStart) { throw new InvalidOperationException("Modeller tracking state corrupted"); } enum1.MoveNext(); var enumerator = AdvancementEnumerable(enum1).GetEnumerator(); return(() => { if (enumerator.MoveNext()) { return enumerator.Current; } enumerator.Dispose(); return TotalTimer; }); }
StartwatchModeller() { SetupTimer = _current = new Startwatch(); _parents = new Stack <Startwatch>(); _tracking = new List <Startwatch>(); TotalTimer = AddNext(); BeforeStart = PushChild(); SetupTimer.Stop(); }
/// <summary> /// Stop time tracking on the Startwatch, allowing for representation of a time period. /// </summary> /// <returns>true if the watch was running before the call, false if it was already stopped</returns> public bool Stop() { if (_stopTimestamp.Value == 0) { Startwatch.QueryPerformanceCounter(out _stopTimestamp.Value); return(true); } return(false); }
/// <summary> /// Internal constructor to allow creation of a stopwatch that uses previous sibling 'end' timestamp as the 'start' /// for this watch, and uses the assigned parents 'end' timestamp as the 'end' for this watch. /// </summary> Startwatch(Startwatch sibling, ISibling fakeParentParameter, Startwatch parent, IParent parent1) { if (parent == null) { throw new ArgumentNullException("parent"); } _startTimestamp = sibling._stopTimestamp; _stopTimestamp = parent._stopTimestamp; }
/// <summary> /// Create new scoped event pushing the current one onto the stack. Start / stop times will not /// be linked but the other timers on the stack will continue measuring time. The pushed event /// will be defined by the provided stopwatch instead of one created by the performance tracker. /// The event will be managed in the same way as other events, but some behavior will be dependent /// on the state of the provided stopwatch. /// </summary> public IUnstoppablePerformanceEvent PushCustomEvent(Startwatch watch) { if (_current == _beforeFirstEvent) { NextEvent(); } _hierarchy.Push(_current); return(_current = new PerformanceEvent(watch)); }
/// <summary> /// Create a new timer that is sequential to the previous one. /// A call to next is required for each call of this function (to stop the timer). /// </summary> public Startwatch AddNext() { if (_current == null) { throw new InvalidModellerStateException(); } var result = _current = _current.CreateSibling(); _tracking.Add(result); return(result); }
/// <summary> /// Create a new timer which is the last child of a parent. /// A call to next <b>is not</b> required for each call to this function. /// The timer created by this function will never be returned by the advancement function. /// </summary> public Startwatch PopNext() { if (_current == null) { throw new InvalidModellerStateException(); } var result = _current = _current.CreateLastSibling(_parents.Peek()); // since it's the last sibling automatically pop the scope back to the parent Pop(); return(result); }
/// <summary> /// Create a new timer which is the first child of the parent. /// A call to next is required for each call to this function (to stop the timer). /// </summary> public Startwatch PushChild() { if (_current == null) { throw new InvalidModellerStateException(); } _parents.Push(_current); var result = _current = _current.CreateChild(); _tracking[_tracking.Count - 1] = result; // overwrite parent in _tracking return(result); }
/// <summary> /// Initialize new Startwatch from System.Diagnostics.Stopwatch, /// if the System.Diagnostics.Stopwatch is actively running then the Startwatch will be running and have the same initial duration /// if the System.Diagnostics.Stopwatch is stopped then the Startwatch will be stopped /// the Startwatch will not be synchronized to the System.Diagnostics.Stopwatch in any way after it is created /// </summary> public static Startwatch FromStopwatch(Stopwatch watch) { if (watch.IsRunning) { long result; Startwatch.QueryPerformanceCounter(out result); return(new Startwatch(result - watch.ElapsedTicks)); } else { return(new Startwatch(0, watch.ElapsedTicks)); } }
/// <summary> /// This implements all the confusing logic about stopping the timers at the right times /// </summary> IEnumerable <Startwatch> AdvancementEnumerable(IEnumerator <Startwatch> enumerator) { Startwatch prev = BeforeStart; while (enumerator.MoveNext()) { // don't stop the timer if it's stop event is linked to the next one prev.Stop(); yield return(prev = enumerator.Current); } if (prev != null) { prev.Stop(); } enumerator.Dispose(); }
/// <summary> /// Goes up the hierarchy of timers to the parent without creating an explicit timer. /// A call to next <b>is not</b> required after calling this function because /// no timer is created. /// </summary> public StartwatchModeller Pop() { if (_current == null) { throw new InvalidModellerStateException(); } // don't allow user to go outside the 'total' if (_parents.Peek() == TotalTimer) { return(this); } var result = _current = _parents.Pop(); _tracking.Add(result); return(this); }
public PerformanceEventTracker() { var setupWatch = new Startwatch(); _setupEvent = new PerformanceEvent(setupWatch); var realTotalWatch = setupWatch.CreateSibling(); _realTotalEvent = new PerformanceEvent(realTotalWatch); var beforeFirstWatch = realTotalWatch.CreateChild(); _beforeFirstEvent = new PerformanceEvent(beforeFirstWatch); _current = _beforeFirstEvent; _hierarchy = new Stack <PerformanceEvent>(); _hierarchy.Push(_realTotalEvent); _setupEvent.EventCompleted(); }
/// <summary> /// internal constructor that allows creation of a child stopwatch from parent /// </summary> Startwatch(Startwatch parent, IParent fakeParentParameter) { _startTimestamp = parent._startTimestamp; _stopTimestamp = new RefTimestamp(); }
/// <summary> /// internal constructor that allows creation of a sibling stopwatch from older sibling /// </summary> Startwatch(Startwatch sibling, ISibling fakeParentParameter) { _startTimestamp = sibling._stopTimestamp; _stopTimestamp = new RefTimestamp(); }
/// <summary> /// Represents an Startwatch that is a sibling, but also shares the end event of the provided parent. This /// is a somewhat less common event but can be useful when used correctly and in certain circumstances /// </summary> public Startwatch CreateLastSibling(Startwatch parent) { return(new Startwatch(this, (ISibling)null, parent, (IParent)null)); }
internal PerformanceEvent(Startwatch watch) { _watch = watch; _behaviors = new List <Action <IUnstoppablePerformanceEvent> >(); }
internal DisposableController(Startwatch controlled) { Controlled = controlled; }
/// <summary> /// Creates a scoped event that is defined by the provided stopwatch. The event will be managed /// in the same way as other performance events, but some behavior is going to be /// dependent on the state of the provided stopwatch. /// If the previous event was not stopped prior to calling NewEvent(), the previous event /// will be stopped automatically. /// </summary> public IUnstoppablePerformanceEvent AddCustomEvent(Startwatch watch) { _current.EventCompleted(); return(_current = new PerformanceEvent(watch)); }
/// <summary> /// Create a started stopwatch /// </summary> public Startwatch() { _stopTimestamp = new RefTimestamp(); _startTimestamp = new RefTimestamp(); Startwatch.QueryPerformanceCounter(out _startTimestamp.Value); }