AutoMapper vs. QuickMapper vs. Reflection

In this post I would like to Compare the Speed Performance between:

  • AutoMapper
  • Reflection
  • Manual Mapper

AutoMapper

AutoMapper is a well-known framework for Mapping Properties between Class Instances.  It is very useful in the case of DTO to Entity mapping & vice-versa.

Reflection

Here I am writing my own Mapping code using .Net Reflection.

Manual Mapper

Here I will be using Manual code for assigning the property values.

Scenario

I am using an Entity class of 10 Properties and Creating 100K instances.  Let us see whether AutoMapper performs better than Raw Reflection code.

Following is the Entity class.

public class Entity
{
     public string Property1 { get; set; }
     public string Property2 { get; set; }
     public string Property3 { get; set; }
     public string Property4 { get; set; }
     public string Property5 { get; set; }
     public string Property6 { get; set; }
     public string Property7 { get; set; }
     public string Property8 { get; set; }
     public string Property9 { get; set; }
     public string Property10 { get; set; }
}

Following is the Dto class.

public class Dto
{
     public string Property1 { get; set; }
     public string Property2 { get; set; }
     public string Property3 { get; set; }
     public string Property4 { get; set; }
     public string Property5 { get; set; }
     public string Property6 { get; set; }
     public string Property7 { get; set; }
     public string Property8 { get; set; }
     public string Property9 { get; set; }
     public string Property10 { get; set; }
}

Following is the AutoMapper Nuget package name.

image

Following is the Reflection code.

public class ReflectionMapper
     {
         public static List<TResult> Map<TSource, TResult>(IList<TSource> sourceList) where TResult : new()
         {
             var result = new List<TResult>(sourceList.Count);

            PropertyDescriptorCollection psrc = TypeDescriptor.GetProperties(typeof(TSource));
             PropertyDescriptorCollection presult = TypeDescriptor.GetProperties(typeof(TResult));

            TResult obj;
             Object colVal;
             string field1 = “”;
             string field2 = “”;

            foreach (TSource item in sourceList)
             {
                 obj = new TResult();

                for (int iResult = 0; iResult < presult.Count; iResult++)
                 {
                     PropertyDescriptor propResult = presult[iResult];
                     field1 = propResult.Name;

                    for (int ix = 0; ix < presult.Count; ix++)
                     {
                         PropertyDescriptor propSource = psrc[ix];

                        field2 = propSource.Name;

                        if (field1 == field2)
                         {
                             colVal = propSource.GetValue(item) ?? null;
                             propResult.SetValue(obj, colVal);
                         }
                     }
                 }

                result.Add(obj);
             }
             return result;
         }

Following is the Manual Mapping code.

public class ReflectionMapper
     {
         public static List<TResult> Map<TSource, TResult>(IList<TSource> sourceList) where TResult : new()
         {
             var result = new List<TResult>(sourceList.Count);

            PropertyDescriptorCollection psrc = TypeDescriptor.GetProperties(typeof(TSource));
             PropertyDescriptorCollection presult = TypeDescriptor.GetProperties(typeof(TResult));

            TResult obj;
             Object colVal;
             string field1 = “”;
             string field2 = “”;

            foreach (TSource item in sourceList)
             {
                 obj = new TResult();

                for (int iResult = 0; iResult < presult.Count; iResult++)
                 {
                     PropertyDescriptor propResult = presult[iResult];
                     field1 = propResult.Name;

                    for (int ix = 0; ix < presult.Count; ix++)
                     {
                         PropertyDescriptor propSource = psrc[ix];

                        field2 = propSource.Name;

                        if (field1 == field2)
                         {
                             colVal = propSource.GetValue(item) ?? null;
                             propResult.SetValue(obj, colVal);
                         }
                     }
                 }

                result.Add(obj);
             }
             return result;
         }

On The Marks!

I have used a Stopwatch for getting the Milliseconds after each operation.  Following is the testing code.

Mapper.Initialize(cfg => cfg.CreateMap<Entity, Dto>());

           IList<Entity> entities = new List<Entity>();

           Stopwatch watch = Stopwatch.StartNew();

           for (int i = 1; i <= 100000; i++)
            {
                Entity entity = new Entity()
                {
                    Property1 = “test value”,
                    Property2 = “test value”,
                    Property3 = “test value”,
                    Property4 = “test value”,
                    Property5 = “test value”,
                    Property6 = “test value”,
                    Property7 = “test value”,
                    Property8 = “test value”,
                    Property9 = “test value”,
                    Property10 = “test value”,
                };
                entities.Add(entity);
            }
            Console.WriteLine(“List Creation: ” + watch.ElapsedMilliseconds.ToString());

           watch.Start();
            IList<Dto> dtosManual = ManualMap(entities);
            Console.WriteLine(“Manual Mapper: ” + watch.ElapsedMilliseconds.ToString());

           watch.Start();
            IList<Dto> dtos = Mapper.Map<IList<Dto>>(entities);
            Console.WriteLine(“Auto Mapper: ” + watch.ElapsedMilliseconds.ToString());

           watch.Start();
            IList<Dto> dtos2 = ReflectionMapper.Map<Entity, Dto>(entities);
            Console.WriteLine(“Reflection Mapper: ” + watch.ElapsedMilliseconds.ToString());

           Console.ReadKey(false);

Following is the Results.

image

Summary

Manual Mapping is the Fastest. Recommended for N^N mapping scenarios.

AutoMapper is next.  The mapping speed is good & negligeble considering current high power machines with scalability in mind.

Reflection Code is slower.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s