예제 #1
0
        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);
        }