前两天看到一篇说Automapper为什么比用反射快的文章,觉得挺有意思,反射的性能低老早就知道,但是一直没上手测过,对于反射性能优化也不知道。今天也没什么事情,想到这个让我好奇心按捺不住了,今天就写个测试一下。
使用反射和Automapper组件分别实现 将对象转换成另一个对象
public class PersonSource { public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } public string City { get; set; } public string Region { get; set; } public string PostalCode { get; set; } public string Country { get; set; } public string Phone { get; set; } public string FatherName { get; set; } public string MatherName { get; set; } public string Fax { get; set; } } public class Person { public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } public string City { get; set; } public string Region { get; set; } public string PostalCode { get; set; } public string Country { get; set; } public string Phone { get; set; } public string FatherName { get; set; } public string MatherName { get; set; } public string Fax { get; set; } }
public class Auto { public static TDestination Mapper<TSource, TDestination>(TSource source) where TSource : class where TDestination : class { var typeSource = source.GetType(); var typeDestination = typeof(TDestination); var propsSource = typeSource.GetProperties(); var dest = Activator.CreateInstance(typeDestination); var propsDestination = dest.GetType().GetProperties(); foreach (var prop in propsSource) { var obj = prop.GetValue(source); var propDestination = propsDestination.FirstOrDefault(t => t.Name == prop.Name); if (propDestination != null) { propDestination.SetValue(dest, obj); } } return dest as TDestination; } }
代码如下:
[MemoryDiagnoser] public class BenchmarkDemo { public List<PersonSource> GetList() { List<PersonSource> list = new List<PersonSource>(); Enumerable.Range(0, 1_000_000).ToList().ForEach(x => { PersonSource personSource = new PersonSource { Name = "张三", Age = x, Address = "Beijing", City = "ShangHai", Region = "Huabei", PostalCode = "10000", Country = "China", Phone = "15200329999", FatherName = "老张", MatherName = "零零", Fax = "2200-7112-555" }; list.Add(personSource); }); return list; } [Benchmark] public void MyAutoTest() { var list = GetList(); list.ForEach(t => { Person destination = Auto.Mapper<PersonSource, Person>(t); }); } [Benchmark] public void AutoMapperTest() { var list = GetList(); var config = new MapperConfiguration(cfg => { cfg.CreateMap<PersonSource, Person>(); }); IMapper iMapper = config.CreateMapper(); list.ForEach(t => { Person destination = iMapper.Map<PersonSource, Person>(t); }); } }
static void Main(string[] args) { var summary = BenchmarkRunner.Run<BenchmarkDemo>(); }
运行代码结果如下:
上图可以看到,在转换一百万个对象时,使用反射比使用Automapper组件耗时更多 (一百万个对象转换大概耗时反射是Automapper的10倍,一千万个对象转换时 反射是Automapper的20倍),占用的内存也更多。
下一篇我们一起探究一下Automapper是如何做到如此高性能的,看看它是用什么方式优化反射的。