EmitMapper,AutoMapper,NLiteMapper和手工映射性能大比拼
2015-06-02 09:24
651 查看
在大比拼之前先讲一个小插曲,我这个人以前比较低调,做了很多好东西仅仅在公司内的朋友圈项目圈内分享,很少在博客园内进行分享,后来在dudu 老大的文章博客园现代化建设——AutoMapper有感便推荐一下OOMapper 组件,于是乎接连写了几篇入门性的介绍使用文章:开发人员必备工具:OOMapper
OO Mapper 实践(上篇)
OO Mapper 实践(下篇)
在园友Repository 兄的NLiteMapper与EmitMapper性能简单比较中了解到NLiteMapper与EmitMapper的性能巨大差距,于是乎进行了两天的性能优化,同时总结了优化过程:一次性能优化最佳实践。在这里非常感谢Repository 兄的测试,也非常感谢他把OOMapper纠正为NLiteMapper,否则NLiteMapper的性能是非常低下的,同时感谢dudu,感谢博客园给大家一个平台,在这个平台使我学到了很多很多...... 不说废话进入主题。 准备工作: 软硬件环境:VS2008,.net3.5, xp 双核
测试组件(都是最新Release版本):AutoMapper.dll(v2.0), EmitMappe.dll (V1.0),NLite.dll(V1.0)
性能测试工具:老赵的CodeTimer 测试接口代码:
为了输出更友好的结果定义一下测试元数据代码:
利用NLite的Mini容器书写测试框架代码如下:测试次数10万次
这样完成了测试框架的搭建,现在就开始书写测试代码了。 定义测试数据:
定义测试基类:
手工映射代码:
AutoMapper 映射代码:
EmitMapper映射代码:
EmitMapper映射器默认不支持Flatter 映射,如果支持需要写自定义配置:+ View Code NLiteMapper映射代码:
Ok,完成代码用Release编译,然后再输出bin中找到exe文件,连续执行三次,下面是三次执行结果的截图:
通过测试结果可以看出: 手工映射速度最快
EmitMapper第二(大约比手工慢了2-6倍,)
NLiteMapper第三(大约比EmitMapper慢了3倍)
最后是AutoMapper(大约比手工慢了200倍)
内存开销结果:手工映射 Gen 0: 3
EmitMapper Gen 0:3
NLiteMapperGen 0: 4
AutoMapperGen 0:173
总结 :无论从性能和内存EmitMapper都接近于手工,NLiteMapper次之,AutoMapper最后。NLiteMapper,EmitMapper,AutoMapper都是通过Emit的方式进行Get和Set的,为什么性能差别如此之大,设想如果NLiteMapper不进行优化的话(NLiteMapper一直是通过Emit方式进行的),那么NLiteMapper肯定是高高垫背的(NLiteMapper比EmitMapper慢了15000倍)。。。。。。 这次测试结果不代表整体结果,仅仅代表Class->Class(包括级联) 的映射性能,欢迎大家对这几种OO映射器进行性能比较。
原文地址:http://www.cnblogs.com/netcasewqs/archive/2011/04/13/2014684.html
OO Mapper 实践(上篇)
OO Mapper 实践(下篇)
在园友Repository 兄的NLiteMapper与EmitMapper性能简单比较中了解到NLiteMapper与EmitMapper的性能巨大差距,于是乎进行了两天的性能优化,同时总结了优化过程:一次性能优化最佳实践。在这里非常感谢Repository 兄的测试,也非常感谢他把OOMapper纠正为NLiteMapper,否则NLiteMapper的性能是非常低下的,同时感谢dudu,感谢博客园给大家一个平台,在这个平台使我学到了很多很多...... 不说废话进入主题。 准备工作: 软硬件环境:VS2008,.net3.5, xp 双核
测试组件(都是最新Release版本):AutoMapper.dll(v2.0), EmitMappe.dll (V1.0),NLite.dll(V1.0)
性能测试工具:老赵的CodeTimer 测试接口代码:
[Contract] public interface IObjectToObjectMapper { //初始化映射器 void Initialize(); //执行映射 void Map(); }
为了输出更友好的结果定义一下测试元数据代码:
//测试映射器元数据 public interface IMapperMetadata { //目录 string Category { get; } //名称 string Name { get; } string Descrption { get; } } //映射器元数据注解 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] [MetadataAttributeAttribute] public class MapperAttribute : ComponentAttribute { public string Category { get; set; } public string Name { get; set; } public string Descrption { get; set; } }
利用NLite的Mini容器书写测试框架代码如下:测试次数10万次
class Program { [InjectMany] private Lazy<IObjectToObjectMapper,IMapperMetadata>[] Mappers; //初始化映射器,并做一次映射操作 void Init() { foreach (var item in Mappers) { item.Value.Initialize(); item.Value.Map(); } } //进行测试 void Run() { foreach (var item in Mappers) CodeTimer.Time(item.Metadata.Category +"->" + item.Metadata.Name , 100000,() => item.Value.Map()); } static void Main(string[] args) { ServiceRegistry.RegisteryFromAssemblyOf<Program>(); var host = new Program(); ServiceRegistry.Compose(host); host.Init(); host.Run(); Console.Read(); } }
这样完成了测试框架的搭建,现在就开始书写测试代码了。 定义测试数据:
public class ModelObject { public DateTime BaseDate { get; set; } public ModelSubObject Sub { get; set; } public ModelSubObject Sub2 { get; set; } public ModelSubObject SubWithExtraName { get; set; } } public class ModelSubObject { public string ProperName { get; set; } public ModelSubSubObject SubSub { get; set; } } public class ModelSubSubObject { public string IAmACoolProperty { get; set; } } public class ModelDto { public DateTime BaseDate { get; set; } public string SubProperName { get; set; } public string Sub2ProperName { get; set; } public string SubWithExtraNameProperName { get; set; } public string SubSubSubIAmACoolProperty { get; set; } }
定义测试基类:
public abstract class MapperBase : IObjectToObjectMapper { protected ModelObject _source; protected ModelDto _target; protected virtual void OnInitialize() { } public void Initialize() { OnInitialize(); _source = new ModelObject { BaseDate = new DateTime(2007, 4, 5), Sub = new ModelSubObject { ProperName = "Some name", SubSub = new ModelSubSubObject { IAmACoolProperty = "Cool daddy-o" } }, Sub2 = new ModelSubObject { ProperName = "Sub 2 name" }, SubWithExtraName = new ModelSubObject { ProperName = "Some other name" }, }; } public abstract void Map(); }
手工映射代码:
[Mapper(Category = "Flattening.Class", Name = "Manual")] public class ManualMapper : MapperBase { public override void Map() { var destination = new ModelDto { BaseDate = _source.BaseDate, Sub2ProperName = _source.Sub2.ProperName, SubProperName = _source.Sub.ProperName, SubSubSubIAmACoolProperty = _source.Sub.SubSub.IAmACoolProperty, SubWithExtraNameProperName = _source.SubWithExtraName.ProperName }; } }
AutoMapper 映射代码:
[Mapper(Category = "Flattening.Class", Name = "AutoMapper")] public class AutoMapperWrapper : MapperBase { protected override void OnInitialize() { AutoMapper.Mapper.Initialize(cfg => { cfg.CreateMap<ModelObject, ModelDto>(); }); AutoMapper.Mapper.AssertConfigurationIsValid(); } public override void Map() { _target =AutoMapper.Mapper.Map<ModelObject, ModelDto>(_source); } }
EmitMapper映射代码:
[Mapper(Category = "Flattening.Class", Name = "EmitMapper")] public class EmitMapperWrapper : MapperBase { ObjectsMapper<ModelObject, ModelDto> mapper; protected override void OnInitialize() { mapper = ObjectMapperManager.DefaultInstance.GetMapper<ModelObject, ModelDto>(new FlatteringConfig()); } protected override ModelDto MapImp() { return mapper.Map(Source); } }
EmitMapper映射器默认不支持Flatter 映射,如果支持需要写自定义配置:+ View Code NLiteMapper映射代码:
[Mapper(Category = "Flattening.Class", Name = "NLiteMapper")] public class NLiteMaperWrapper : MapperBase { private NLite.Mapping.IMapper<ModelObject, ModelDto> mapper; protected override void OnInitialize() { base.OnInitialize(); mapper = NLite.Mapper.CreateMapper<ModelObject, ModelDto>(); } public override void Map() { _target = mapper.Map(_source); } }
Ok,完成代码用Release编译,然后再输出bin中找到exe文件,连续执行三次,下面是三次执行结果的截图:
1234567891011121314151617181920212223242526272829 | ------ Test started: Assembly: NLite.Test.dll ------ Flattening.Class->AutoMapper Time Elapsed: 1,112ms CPU Cycles: 6,718,750 Gen 0: 173 Gen 1: 1 Gen 2: 0 Flattening.Class->NLiteMapper Time Elapsed: 68ms CPU Cycles: 781,250 Gen 0: 4 Gen 1: 1 Gen 2: 0 Flattening.Class->EmitMapper Time Elapsed: 23ms CPU Cycles: 156,250 Gen 0: 3 Gen 1: 0 Gen 2: 0 Flattening.Class->Manual Time Elapsed: 8ms CPU Cycles: 0 Gen 0: 3 Gen 1: 1 Gen 2: 0 |
1234567891011121314151617181920212223242526272829303132 | ------ Test started: Assembly: NLite.Test.dll ------ Flattening.Class->AutoMapper Time Elapsed: 1,701ms CPU Cycles: 10,468,750 Gen 0: 173 Gen 1: 0 Gen 2: 0 Flattening.Class->NLiteMapper Time Elapsed: 69ms CPU Cycles: 781,250 Gen 0: 4 Gen 1: 1 Gen 2: 0 Flattening.Class->EmitMapper Time Elapsed: 22ms CPU Cycles: 0 Gen 0: 3 Gen 1: 0 Gen 2: 0 Flattening.Class->Manual Time Elapsed: 10ms CPU Cycles: 312,500 Gen 0: 3 Gen 1: 1 Gen 2: 0 1 passed, 0 failed, 0 skipped, took 2.98 seconds (NUnit 2.5.5). |
1234567891011121314151617181920212223242526272829303132 | ------ Test started: Assembly: NLite.Test.dll ------ Flattening.Class->AutoMapper Time Elapsed: 1,205ms CPU Cycles: 10,156,250 Gen 0: 177 Gen 1: 0 Gen 2: 0 Flattening.Class->NLiteMapper Time Elapsed: 66ms CPU Cycles: 781,250 Gen 0: 4 Gen 1: 0 Gen 2: 0 Flattening.Class->EmitMapper Time Elapsed: 18ms CPU Cycles: 312,500 Gen 0: 3 Gen 1: 0 Gen 2: 0 Flattening.Class->Manual Time Elapsed: 9ms CPU Cycles: 0 Gen 0: 3 Gen 1: 0 Gen 2: 0 1 passed, 0 failed, 0 skipped, took 2.56 seconds (NUnit 2.5.5). |
EmitMapper第二(大约比手工慢了2-6倍,)
NLiteMapper第三(大约比EmitMapper慢了3倍)
最后是AutoMapper(大约比手工慢了200倍)
内存开销结果:手工映射 Gen 0: 3
EmitMapper Gen 0:3
NLiteMapperGen 0: 4
AutoMapperGen 0:173
总结 :无论从性能和内存EmitMapper都接近于手工,NLiteMapper次之,AutoMapper最后。NLiteMapper,EmitMapper,AutoMapper都是通过Emit的方式进行Get和Set的,为什么性能差别如此之大,设想如果NLiteMapper不进行优化的话(NLiteMapper一直是通过Emit方式进行的),那么NLiteMapper肯定是高高垫背的(NLiteMapper比EmitMapper慢了15000倍)。。。。。。 这次测试结果不代表整体结果,仅仅代表Class->Class(包括级联) 的映射性能,欢迎大家对这几种OO映射器进行性能比较。
原文地址:http://www.cnblogs.com/netcasewqs/archive/2011/04/13/2014684.html
相关文章推荐
- Android Context 上下文 你必须知道的一切
- android handler消息机制
- Android 自定义控件 优雅实现元素间的分割线 (支持3.0以下)
- vlc-android 中调用用libvlcjni.so实现流媒体播放
- swfobject.embedSWF与div的z-index问题
- iPhone6+ 以及 iOS8适配:Masonry介绍——速成Autolayout
- SWFObject: 基于Javascript的Flash媒体版本检测与嵌入模块
- mac下双开unity
- android 比较靠谱的图片压缩
- Gradle Android最新自动化编译脚本教程(提供demo源码)
- Android SurfaceView实战 带你玩转flabby bird (下)
- 致创业者:APP已死 服务永生
- Android 打造形形色色的进度条 实现可以如此简单
- Android 你应该知道的学习资源 进阶之路贵在坚持
- 【Android】Android 权限大全
- 用c#开发微信 (10) JS-SDK 基本用法- 分享接口“发送到朋友”
- Android进程间通信系列-----------进程间的数据传递载体Parcel
- 设计移动App的十大技巧
- Android之发送短信和接收验证码
- 一篇文章让你读懂iOS和Android的历史起源