Monday, July 13, 2015

C# Battle - Dynamic Array -versus- Generic Collection

In a previous post I insinuated that using a dynamic array in C#, rather than a dynamic structure might show a certain lack of basic programming skills.  Well, after getting my daughter off to work early Saturday morning, a storm rolled in, throwing out my plans to perform a little yard maintenance.  So...  what to do?  How about a little computer play while drinking my morning coffee.

After all, drinking coffee while practicing my guitar has far too many times caused scares due to the possibility of spilled coffee!

So, I set out to prove that Dynamic Arrays are worse performers than Collections in C#.  Well...  For my tests, my presumptions were proven incorrect.  My little test showed that when loading image bitmaps from PNG files into a Dynamic Array, there is only a marginal difference loading into a C# Collection.

Machine Baseline...
CPU: Intel Core i3-3240 @ 3.4 GHz
RAM: 8GB
Windows Version: 7 Ultimate 64 bit.
Hard Drive: ADATA SP920 512MB SSD drive
Number of images to load: 9727
Image size: All are 640 x 480

Read on for the code and specific results...
Code using collection to load images...

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Drawing;
using System.Text;

// simple program to load about 9000 images into a Collection
namespace ListTest
{
    class Program
    {
        static Collection<Bitmap> imgList = new Collection<Bitmap>();        
        static void Main(string[] args)
        {
            DateTime start = DateTime.Now;
            Console.WriteLine("Test using Collection...");
            Console.WriteLine("Starting: " + start.ToString());
            LoadList();
            Console.WriteLine("Ending: " + DateTime.Now.ToString());
            TimeSpan timespent = DateTime.Now - start;
            Console.WriteLine(timespent.Days.ToString() + ":" + timespent.Hours.ToString() + ":" + timespent.Minutes.ToString() + ":" + timespent.Seconds.ToString());
            Console.ReadKey();
        }

        static void LoadList()
        {
            var theFiles = Directory.EnumerateFiles(@"C:\temp\img\", "*.png");
            UInt32 filesLoaded = 0;
            foreach (string fileName in theFiles)
            {
                using (FileStream ifs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    Image bTmp = Image.FromStream(ifs);
                    imgList.Add((Bitmap)bTmp);
                    filesLoaded++;
                    if (filesLoaded % 500 == 0)
                    { Console.WriteLine("Files imported: " + filesLoaded.ToString()); }
                }
            }
            Console.WriteLine("**DONE - Total Files imported: " + filesLoaded.ToString()); 
        }
    }
}

Code using dynamic array to load images...

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Drawing;
using System.Text;

// simple program to load about 9000 images into an array
namespace ListTest
{
    class Program
    {
        static Bitmap[] imgList;
        static void Main(string[] args)
        {
            DateTime start = DateTime.Now;
            Console.WriteLine("Test using Array...");
            Console.WriteLine("Starting: " + start.ToString());
            LoadList();
            Console.WriteLine("Ending: " + DateTime.Now.ToString());
            TimeSpan timespent = DateTime.Now - start;
            Console.WriteLine(timespent.Days.ToString() + ":" + timespent.Hours.ToString() + ":" + timespent.Minutes.ToString() + ":" + timespent.Seconds.ToString());
            Console.ReadKey();
        }

        static void LoadList()
        {
            var theFiles = Directory.EnumerateFiles(@"C:\temp\img\", "*.png");
            UInt32 filesLoaded = 0;
            foreach (string fileName in theFiles)
            {
                using (FileStream ifs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    Image bTmp = Image.FromStream(ifs);
                    Array.Resize(ref imgList, (imgList==null?1:imgList.Length + 1));  // add item to array
                    imgList[imgList.Length-1] = (Bitmap)bTmp;  // copy bitmap to new array element
                    filesLoaded++;
                    if (filesLoaded % 500 == 0)
                    { Console.WriteLine("Files imported: " + filesLoaded.ToString()); }
                }
            }
            Console.WriteLine("**DONE - Total Files imported: " + filesLoaded.ToString());
        }
    }
}
----------
After three runs, the average time required to load the 9727 images using a Collection was 1 minute, 15 seconds with an average memory footprint of about 6.740 GB.


After three runs, the average time required to load the same 9727 images using an array was 1 minute, 16 seconds with an average memory footprint of about 6.930 GB.

While this does indicate there may be a minor advantage in terms of memory footprint and performance when using a Collection over an Array in usage scenarios such as these, the difference is certainly not as drastic as I thought it would be before running these tests.


No comments:

Post a Comment