public void ResizeTest(int sw, int sh, int tw, int th)
        {
            Size sourceSize = new Size(sw, sh);
            Size targetSize = new Size(tw, th);

            using var bmpRef = Icons.Information.ExtractBitmap(sourceSize);

            var perfTest = new PerformanceTest {
                Iterations = 100, CpuAffinity = null, TestName = $"{sw}x{sh} to {tw}x{th}"
            };

            foreach (var mode in new[] { InterpolationMode.NearestNeighbor, InterpolationMode.Bilinear, InterpolationMode.HighQualityBicubic })
            {
                perfTest.AddCase(() =>
                {
                    using Bitmap result = new Bitmap(sw, sh);
                    using (Graphics g = Graphics.FromImage(result))
                    {
                        g.InterpolationMode = mode;
                        g.PixelOffsetMode   = PixelOffsetMode.HighQuality;
                        g.DrawImage(bmpRef, new Rectangle(Point.Empty, targetSize), new Rectangle(Point.Empty, sourceSize), GraphicsUnit.Pixel);
                        g.Flush();
                    }
                }, $"DrawImage/{mode}");
            }

            foreach (ScalingMode scalingMode in Enum <ScalingMode> .GetValues())
            {
                perfTest.AddCase(() =>
                {
                    using var result = bmpRef.Resize(targetSize, scalingMode);
                }, $"Resize/{scalingMode}");
            }

            perfTest.DoTest().DumpResults(Console.Out);
        }
        public void CompareProfilingWaysCheapOperation()
        {
            const int iterations = 10000000;

            // 1. Test without warm up
            var test = new PerformanceTest <int>
            {
                TestName   = "DoTest performance without warm up",
                Iterations = iterations,
                WarmUp     = false,
                Repeat     = 5,
            }
            .AddCase(DoNothing, nameof(DoNothing));

            test.DoTest().DumpResults(Console.Out);

            // 2. Test without warm up
            test.TestName = "DoTest performance with warm up";
            test.WarmUp   = true;
            test.DoTest().DumpResults(Console.Out);

            // 3. Direct test
            Console.WriteLine("===========Direct measurement test===============");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            // warming up
            for (int i = 0; i < iterations; i++)
            {
                DoNothing();
            }

            Stopwatch watch = new Stopwatch();

            watch.Start();
            for (int i = 0; i < iterations; i++)
            {
                DoNothing();
            }

            watch.Stop();
            Console.WriteLine("Total Time: {0:N2} ms", watch.Elapsed.TotalMilliseconds);
            Console.WriteLine();
            Console.WriteLine("The difference of DoTest and Direct measurement is the overhead cost of using a delegate in DoTest.");
            Console.WriteLine();

            // 4. Profiler test
            Console.WriteLine("===========Profiler test===============");
            Profiler.Reset();
            Profiler.AutoSaveResults = false;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            for (int i = 0; i < iterations; i++)
            {
                using (Profiler.Measure("ProfilerTest", "WarmingUp"))
                {
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            for (int i = 0; i < iterations; i++)
            {
                using (Profiler.Measure("ProfilerTest", "SelfCostWithoutOp"))
                {
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            using (Profiler.Measure("ProfilerTest", "TotalWithSubMeasures"))
            {
                for (int i = 0; i < iterations; i++)
                {
                    using (Profiler.Measure("ProfilerTest", "DoNothingCall"))
                        DoNothing();
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            using (Profiler.Measure("ProfilerTest", "PureTotal"))
            {
                for (int i = 0; i < iterations; i++)
                {
                    DoNothing();
                }
            }

            foreach (IMeasureItem item in Profiler.GetMeasurementResults("ProfilerTest"))
            {
                Console.WriteLine("{0}: {1:N2} ms", item.Operation, item.TotalTime.TotalMilliseconds);
            }

            Console.WriteLine();
            Console.WriteLine("PureTotal should be nearly the same as Direct measurement, and PureTotal should be DoNothingCall - SelfCostWithoutOp");
            Console.WriteLine("TotalWithSubMeasures - DoNothingCall = the cost of the Profiler itself (SelfCostWithoutOp does not contain the administration costs of the results)");
        }
        public void CompareProfilingWaysExpensiveOperation()
        {
            const int iterations = 10000;
            var       test       = new PerformanceTest <int>
            {
                TestName   = "DoTest performance without warm up",
                Iterations = iterations,
                WarmUp     = false,
                Repeat     = 5,
            }
            .AddCase(DoSomething, nameof(DoSomething));

            // 1. DoTest without warmup
            test.DoTest().DumpResults(Console.Out);

            test.TestName = "DoTest performance with warmup";
            test.WarmUp   = true;

            // 2. DoTest with warmup
            test.DoTest().DumpResults(Console.Out);

            // 3. Direct test
            Console.WriteLine("===========Direct measurement test===============");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            // warming up
            for (int i = 0; i < iterations; i++)
            {
                DoSomething();
            }

            Stopwatch watch = new Stopwatch();

            watch.Start();
            for (int i = 0; i < iterations; i++)
            {
                DoSomething();
            }

            watch.Stop();
            Console.WriteLine("Total Time: {0:N2} ms", watch.Elapsed.TotalMilliseconds);
            Console.WriteLine();

            // 4. Profiler test
            Console.WriteLine("===========Profiler test===============");
            Profiler.AutoSaveResults = false;
            Profiler.Reset();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            for (int i = 0; i < iterations; i++)
            {
                using (Profiler.Measure("ProfilerTest", "WarmingUp"))
                {
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            for (int i = 0; i < iterations; i++)
            {
                using (Profiler.Measure("ProfilerTest", "SelfCostWithoutOp"))
                {
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            using (Profiler.Measure("ProfilerTest", "TotalWithSubMeasures"))
            {
                for (int i = 0; i < iterations; i++)
                {
                    using (Profiler.Measure("ProfilerTest", "DoSomethingCall"))
                        DoSomething();
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            using (Profiler.Measure("ProfilerTest", "PureTotal"))
            {
                for (int i = 0; i < iterations; i++)
                {
                    DoSomething();
                }
            }

            foreach (IMeasureItem item in Profiler.GetMeasurementResults("ProfilerTest"))
            {
                Console.WriteLine("{0}: {1:N2} ms", item.Operation, item.TotalTime.TotalMilliseconds);
            }

            Console.WriteLine();
            Console.WriteLine("In case of a costly operation the DirectTotal < PureTotal < DoTest < DoSomethingCall < TotalWithSubMeasures should have nearly the same value.");
        }