public static double Measure(Action a, BenchmarkOptions options = default(BenchmarkOptions)) { if (options == default(BenchmarkOptions)) { options = BenchmarkOptions.Default(); } var decompiler = new JitCodeDecompiler(); var warmupCount = options.WarmUpCount; var runCount = options.RunCount; DecompiledMethod before = null; if (options.Decompile) { a(); before = decompiler.DecompileMethod(a.Method, options.DecompileMethodName); } // // Quick Warm Up. // XConsole.WriteLine("Quick Benchmark:"); XConsole.WriteLine($" [1] Warm Up ...({warmupCount})"); for (int i = 0; i < warmupCount; i++) { a(); } Span <double> res = stackalloc double[runCount]; var initialMemory = GC.GetTotalAllocatedBytes(); XConsole.WriteLine($" [2] Running ...({runCount})"); for (int i = 0; i < runCount; i++) { Stopwatch w = new Stopwatch(); w.Start(); { a(); } w.Stop(); res[i] = w.ElapsedMilliseconds; } var memoryAfterRuns = GC.GetTotalAllocatedBytes(); double sum = 0; for (int i = 0; i < res.Length; i++) { XConsole.WriteLine($" [3-{i}] Took: `{res[i]}` ms"); sum += res[i]; } var cursonLeft = XConsole.CursorLeft; var mean = sum / runCount; var stdDev = StdDev(res, mean); var totalMemory = memoryAfterRuns - initialMemory; int separatorLen = cursonLeft + 30 + (runCount * 4); XConsole.DrawSeparator(separatorLen); XConsole.WriteLine($" Mean -> `{string.Format("{0:N4}", mean)}` ms"); XConsole.WriteLine($" StdDev -> `{string.Format("{0:N4}", stdDev)}` ms"); XConsole.WriteLine($" Total Memory -> `{totalMemory}` b\r\n"); var cursorTop = XConsole.CursorTop; XConsole.DrawPlot(30, cursorTop - 5, res.ToArray()); if (options.Decompile) { XConsole.WriteLine($" Decompiling Method: `{options.DecompileMethodName}`"); cursorTop += 2; var after = decompiler.DecompileMethod(before.CodeAddress, before.CodeSize, options.DecompileMethodName); if (before.CodeAddress == after.CodeAddress) { XConsole.WriteLine("Captured Only Single Tier"); var coords1 = PrintCode("Tier0", 1, cursorTop + 1, before); XConsole.SetCursorPosition(0, coords1.y); } else { var coords1 = PrintCode("Tier0", 1, cursorTop, before); var coords2 = PrintCode("Tier1", 50, cursorTop, after); int top = coords1.y > coords2.y ? coords1.y : coords2.y; XConsole.SetCursorPosition(0, top); } } return(mean); }