private void runTest(Func <Stream> test, string label, Label uiLabel, bool breakup)
    {
        int iterations = 10;
        int parallel1  = 4;
        int parallel2  = 8;
        var tasks      = new List <Task>();
        var times      = new ConcurrentStack <double>();
        var elapsed    = new Stopwatch();

        if (breakup)
        {
            GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
            GC.Collect(2, GCCollectionMode.Forced, true);
            Thread.Sleep(1000);
        }

        var tests = new List <Action>();

        tests.AddRange(Enumerable.Repeat <Action>(() => { var sw = new Stopwatch(); sw.Start(); test(); sw.Stop(); times.Push(ticksToMs(sw.ElapsedTicks)); }, iterations));
        foreach (var action in tests.Take(10))
        {
            Task.Run(action).Wait();
        }
        uiLabel.Content = $"{label}:\nSerial x{times.Count}: {times.Average():f2}ms ±{times.StandardDeviation():f2}ms";

        times.Clear();
        elapsed.Restart();
        tasks.Clear();
        foreach (var action in tests.Take(parallel1))
        {
            tasks.Add(Task.Run(action));
        }
        Task.WaitAll(tasks.ToArray());
        elapsed.Stop();
        uiLabel.Content += $"\nParallel x{times.Count}: {times.Average():f2}ms ±{times.StandardDeviation():f2}ms ({ticksToMs(elapsed.ElapsedTicks):f2} elapsed)";

        times.Clear();
        elapsed.Restart();
        tasks.Clear();
        foreach (var action in tests.Take(parallel2))
        {
            tasks.Add(Task.Run(action));
        }
        Task.WaitAll(tasks.ToArray());
        elapsed.Stop();
        uiLabel.Content += $"\nParallel x{times.Count}: {times.Average():f2}ms ±{times.StandardDeviation():f2}ms ({ticksToMs(elapsed.ElapsedTicks):f2} elapsed)";
    }
Example #2
0
        static void Main(string[] args)
        {
            Stopwatch decode = new Stopwatch();

            //Load jpeg into reusable byte array
            //var stream = new MemoryStream(File.ReadAllBytes("large.jpg"));
            var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("GdiBench.mountain-jpg.jpg");
            var ms = new MemoryStream();
            stream.CopyTo(ms);
            var bytes = ms.ToArray();

            //Create PNG version via IR
            MemoryStream pngStream = new MemoryStream();
            ImageBuilder.Current.Build(new MemoryStream(bytes), pngStream, new Instructions("format=png"));
            var pngBytes = ImageResizer.ExtensionMethods.StreamExtensions.CopyToBytes(pngStream, true);

            var endecodingBenchmarks = new List<Tuple<string, Action>>();

            //Since we're doing so many decoding tests, make a template
            Func<byte[],Func<Stream,Image>,Action> CreateDecodeTest = (byte[] inputBytes, Func<Stream, Image> decoder) => {
                return () => {
                    var bytesRead = new ConcurrentStack<long>();
                    Timing.MeasureOperation(delegate(object input, TimeSegment time)
                    {
                        var readStream = new InstrumentedMemoryStream((byte[])input);
                        time.MarkStart();
                        using (var bit = decoder(readStream))
                        {
                            time.MarkStop();
                            bytesRead.Push(readStream.BytesRead);
                            var test = bit.Width;
                        }

                    }, inputBytes);
                    Console.WriteLine("Average bytes read per thread: " + bytesRead.Average().ToString());
                };
            };

            endecodingBenchmarks.Add(new Tuple<string, Action>("Measure new Bitmap(stream,useIcm=true) (jpeg)",
                CreateDecodeTest(bytes, (s) => new Bitmap(s,true))
            ));

            endecodingBenchmarks.Add(new Tuple<string, Action>("Measure new Bitmap(stream,useIcm=true) (png)",
                CreateDecodeTest(pngBytes, (s) => new Bitmap(s, true))
            ));

            endecodingBenchmarks.Add(new Tuple<string, Action>("Measure Bitmap.FromStream(readStream,true,true) (jpeg)",
                CreateDecodeTest(bytes, (s) => Bitmap.FromStream(s, true, true))
            ));

            endecodingBenchmarks.Add(new Tuple<string, Action>("Measure Bitmap.Save (jpeg)",
               () => {
                   Timing.MeasureOperation(delegate(object input, TimeSegment time)
                   {
                       var readStream = new MemoryStream((byte[])input);
                       using (var bit = System.Drawing.Bitmap.FromStream(readStream, false, true))
                       using (EncoderParameters p = new EncoderParameters(1))
                       using (var ep = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)90))
                       {
                           var outStream = new MemoryStream(readStream.Capacity);
                           p.Param[0] = ep;
                           time.MarkStart();
                           bit.Save(outStream, GetImageCodeInfo("image/jpeg"), p);
                           time.MarkStop();
                       }
                   }, bytes);
               }
               ));

            var resizeBenchmarks = new List<Tuple<string, Action>>();
            resizeBenchmarks.Add(new Tuple<string, Action>("Measure DrawImage -> 500x500",
               () =>
               {
                   Timing.MeasureOperation(delegate(object input, TimeSegment time)
                   {
                       var readStream = new InstrumentedMemoryStream((byte[])input);
                       readStream.BytesRead = 0;

                       using (var bit = new Bitmap(readStream, true))
                       {
                           readStream.SleepMsPerReadCall = 50;
                           readStream.BytesRead = 0;

                           var dest = MathUtil.ScaleWithin(bit.Width, bit.Height, 500, 500);

                           using (var canvas = new Bitmap(dest.Item1, dest.Item2))
                           using (var g = Graphics.FromImage(canvas))
                           using (var attrs = new ImageAttributes() { })
                           {
                               attrs.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
                               g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
                               g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                               g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                               g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                               g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                               time.MarkStart();

                               g.DrawImage(bit, new Point[] { new Point(0, 0), new Point(dest.Item1, 0), new Point(0, dest.Item2) },
                                   new Rectangle(0, 0, bit.Width, bit.Height), GraphicsUnit.Pixel, attrs);
                               time.MarkStop();
                               Debug.Assert(readStream.BytesRead == 0);
                           }
                       }

                   }, bytes);
               }));

            resizeBenchmarks.Add(new Tuple<string, Action>("Measure Direct2D DrawImage jpg->500px->jpg",
               () =>
               {
                   Timing.MeasureOperation(delegate(object input, TimeSegment time)
                   {
                       var readStream = new MemoryStream((byte[])input);
                       var outStream = Direct2D.Resize(readStream, 500, 500, () => time.MarkStart(), () => time.MarkStop());
                   }, bytes);
               }));

            endecodingBenchmarks.Add(new Tuple<string, Action>("Measure Direct2D load jpeg",
               () =>
               {
                   Timing.MeasureOperation(delegate(object input, TimeSegment time)
                   {
                       var readStream = new MemoryStream((byte[])input);
                       time.MarkStart();
                       var outStream = Direct2D.Resize(readStream, 500, 500, () => time.MarkStop(), () => { });
                   }, bytes);
               }));

            resizeBenchmarks.Add(new Tuple<string, Action>("Measure Direct2D decode-resize-encode jpg->500px->jpg",
              () =>
              {
                  Timing.MeasureOperation(delegate(object input, TimeSegment time)
                  {
                      var readStream = new MemoryStream((byte[])input);
                      time.MarkStart();
                      var outStream = Direct2D.Resize(readStream, 500, 500, () => { }, () => { });
                      time.MarkStop();
                  }, bytes);
              }));

            resizeBenchmarks.Add(new Tuple<string, Action>("Measure ImageResizer jpg->500px->jpg",
               () =>
               {
                   Timing.MeasureOperation(delegate(object input, TimeSegment time)
                    {
                        var readStream = new MemoryStream((byte[])input);
                        var outStream = new MemoryStream(readStream.Capacity);
                        time.MarkStart();
                        ImageBuilder.Current.Build(readStream, outStream, new Instructions("maxwidth=500&maxheight=500&format=jpg"));
                        time.MarkStop();

                    }, bytes);
               }));

            var all = new List<Tuple<string, Action>>();
            all.AddRange(endecodingBenchmarks);
            all.AddRange(resizeBenchmarks);

            List<Tuple<string, Action>> toRun = null;

            Console.WriteLine("Benchmark (a) all, (e) encode/decode, (r) resizing, or select (i)ndividually");
            var key = Console.ReadKey(true).Key;
            if (key == ConsoleKey.A) toRun = all;
            else if (key == ConsoleKey.E) toRun = endecodingBenchmarks;
            else if (key == ConsoleKey.R) toRun = resizeBenchmarks;
            else
            {
                //Ask which ones to run
                toRun = new List<Tuple<string, Action>>();
                foreach (var t in all)
                {
                    Console.WriteLine("(y) to schedule: " + t.Item1);
                    if (Console.ReadKey(true).Key == ConsoleKey.Y)
                        toRun.Add(t);
                }
                Console.WriteLine();
                Console.WriteLine();
            }

            //Run selected benchmarks
            foreach (var t in toRun)
            {
                Console.WriteLine(t.Item1);
                t.Item2();
                Console.WriteLine();
                Console.WriteLine();
            }
            Console.WriteLine("Finished. Press any key to exit.");
            Console.ReadKey();
        }