/// <summary> /// Starts the timer for this bloc of code. /// Each timer must be stopped with <see cref="StopCurrentBloc"/> method. Note that you can only stop the last started timer. /// </summary> /// <param name="showAverage">If true, the average time per call will be shown for this bloc of code in the report.</param> /// <param name="arg">An optionnal label to use in addition of the calling method name. Convenient if you need to time more than one bloc of code in a single method body.</param> public static void StartChronometer(string arg = "", bool showAverage = false, bool ignoreStackTrace = false) { string callTrace = "", indentation = ""; foreach (var timer in timers) { indentation += INDENTATION; callTrace += timer.label; } string label = indentation; if (!ignoreStackTrace) { var callingMethod = new System.Diagnostics.StackFrame(1).GetMethod(); string className = callingMethod != null ? callingMethod.ReflectedType.Name : "UnknowClass"; string methodName = callingMethod != null ? callingMethod.Name : "UnknowMethod"; label += className + "." + methodName; } if (!string.IsNullOrEmpty(arg)) { label += "." + arg; } if (!blocTimers.ContainsKey(callTrace + label)) { blocTimers[callTrace + label] = new BlocTimer(label, showAverage); } blocTimers[callTrace + label].Start(); timers.Push(blocTimers[callTrace + label]); }
/// <summary> /// Returns a multiline string presenting the time spent in each timed bloc of code. /// If a single bloc has been called from different code paths, times are dispatched between paths. /// </summary> /// <returns>The multiline report.</returns> public static string GetChronometerReport() { StringBuilder sb = new StringBuilder("Time spent in measured blocs: " + Environment.NewLine); foreach (var label in blocTimers.Keys) { BlocTimer timer = blocTimers[label]; sb.Append(" " + timer.label + " : " + timer.Duration + " ms"); if (timer.showAverage) { sb.Append(" (" + timer.DurationPerCall + " per call)"); } sb.Append(Environment.NewLine); } return(sb.ToString()); }