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.
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.
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.