前言:
我们在很多项目场景中使用对象映射工具,那么使用最多的OOM对象工具也就那几个。今天所说的EmitMapper 和TinyMapper 两者的性能都是很高的,相比autoMapper 速度不知道快了多少倍,因为我平时使用的最多EmitMapper,所在业余时间做了一下测试两者对比。
测试数据:10万条和1000万条,分手动,TinyMapper,EmitMapper分别进行测试。22次用例结果:平均值:(注autoMapper不参与,因为笔者认为性能暂时无法和以上相比)
SELECT TOP (200) typename, AVG(esTime) AS estimed FROM emitTinyMapperData GROUP BY typename ORDER BY 2
结果显示:
手动生成 458 TinyMapper 535 EmitMapper 618
数据加大到:1000万条:
手动生成 458 TinyMapper 525 EmitMapper 593
TestModel数据对象(为了方便看就写在一起了):
1 namespace YGOP.PayCenter.MapperTest 2 { 3 /// <summary> 4 /// 测试对象 5 /// </summary> 6 public class TestModel 7 { 8 public string modelName { get; set; } 9 } 10 11 /// <summary> 12 /// 测试对象A 13 /// </summary> 14 public class TestModelA: TestModel 15 { 16 public string modelNameA { get; set; } 17 public int age { get; set; } 18 public int sex { get; set; } 19 /// <summary> 20 /// 注意此处 21 /// </summary> 22 public OrderItem orderItem { get; set; } 23 } 24 25 public class TestModelB : TestModel 26 { 27 public string modelNameB { get; set; } 28 29 public long sex { get; set; } 30 public int ageB { get; set; } 31 /// <summary> 32 /// 注意此处 33 /// </summary> 34 public string gender { get; set; } 35 public string bak { get; set; } 36 /// <summary> 37 /// 注意此处 38 /// </summary> 39 public OrderItem2 orderItem2 { get; set; } 40 41 } 42 /// <summary> 43 /// 订单子对象测试 44 /// </summary> 45 public class OrderItem 46 { 47 public string orderId { get;set;} 48 public string subId { get; set; } 49 50 public int qty { get; set; } 51 public double price { get; set; } 52 public string bak { get; set; } 53 54 public string qq { get; set; } 55 public bool isMem { get; set; } 56 57 } 58 59 /// <summary> 60 /// 订单子对象测试 61 /// </summary> 62 public class OrderItem2 63 { 64 public string orderId { get; set; } 65 public string itemId { get; set; } 66 67 public string qq { get; set; } 68 public int amount { get; set; } 69 public decimal unitprice { get; set; } 70 71 public bool isMem { get; set; } 72 73 }
测试用例代码:
0.手动生成对象
1 /// <summary> 2 /// 手工生成对象 3 /// </summary> 4 /// <param name="max"></param> 5 /// <returns></returns> 6 private List<TestModelA> HanderCustomObject(int max= 100000) 7 { 8 List<TestModelA> modelAlist = new List<TestModelA>(); 9 10 11 for (int i = 0; i < max; i++) 12 { 13 modelAlist.Add(new TestModelA() 14 { 15 age = i + 10, 16 modelNameA = "测试a" + i, 17 modelName = "测试a" + i, 18 sex = i, 19 orderItem = new OrderItem() 20 { 21 bak = "132" + i, 22 orderId = "orderId" + DateTime.Now.ToString() + i.ToString(), 23 price = i + new Random().Next(20, 100), 24 qty = i, 25 qq = "252445578" + i, 26 subId = "subId" + i 27 , 28 isMem = i % 2 == 0 29 } 30 }); 31 } 32 33 return modelAlist; 34 35 }
1.给 TinyMapper 做对象的关系映射
1 /// <summary> 2 /// 给 TinyMapper 做对象的关系映射 3 /// </summary> 4 private void InitTinyMapperCustomMapper() 5 { 6 7 TinyMapper.Bind<OrderItem, OrderItem2>(mapconfig2Order => 8 { 9 mapconfig2Order.Bind(a => a.qty, b => b.amount); 10 mapconfig2Order.Bind(a => a.price, b => b.unitprice); 11 mapconfig2Order.Bind(a => a.subId, b => b.itemId); 12 mapconfig2Order.Bind(a => a.bak, b => b.amount); 13 }); 14 15 TinyMapper.Bind<TestModelA, TestModelB>(mapConfig => 16 { 17 mapConfig.Ignore(src => src.modelName); 18 mapConfig.Bind(a => a.age, b => b.ageB); 19 mapConfig.Bind(a => a.sex, b => b.gender); 20 mapConfig.Bind(a => a.modelNameA, b => b.modelNameB); 21 mapConfig.Bind(a => a.orderItem, b => b.orderItem2); 22 }); 23 24 25 26 }
2.给EmitMapper 做对象关系的映射
1 /// <summary> 2 /// 给EmitMapper 做对象关系的映射 3 /// </summary> 4 /// <returns></returns> 5 private IMappingConfigurator InitEmitCustomMapper2() 6 { 7 IMappingConfigurator conf = new DefaultMapConfig().ConvertUsing<TestModelA, TestModelB>( 8 v => new TestModelB() 9 { 10 ageB = v.age, 11 gender = (v.sex % 2 == 0 ? "男" : "女"), 12 modelNameB = v.modelNameA, 13 orderItem2 = new OrderItem2() 14 { 15 amount = v.orderItem.qty, 16 itemId = v.orderItem.subId, 17 unitprice = Convert.ToDecimal(v.orderItem.price), 18 qq = v.orderItem.qq, 19 orderId = v.orderItem.orderId, 20 isMem = v.orderItem.isMem 21 } 22 23 }); 24 25 return conf; 26 }
3.最终的调用
1 private void button1_Click(object sender, EventArgs e) 2 { 3 Stopwatch stopwatch = new Stopwatch(); 4 stopwatch.Start(); 5 6 int max = 100000; 7 var modelAlist = HanderCustomObject(); 8 stopwatch.Stop(); 9 string ok1 = string.Format(max + "次,手动生成 所用时间 :{0} 毫秒", stopwatch.ElapsedMilliseconds); 10 textBox1.AppendText(ok1 + " "); 11 stopwatch.Start(); 12 InitTinyMapperCustomMapper(); 13 var ss = TinyMapperHelper.Instance.Convert<List<TestModelA>, List<TestModelB>>(modelAlist); 14 stopwatch.Stop(); 15 string ok = string.Format(max + "次,TinyMapper 所用时间 :{0} 毫秒", stopwatch.ElapsedMilliseconds); 16 textBox1.AppendText(ok + " "); 17 18 //Thread.Sleep(1000); 19 stopwatch.Start(); 20 var conf= InitEmitCustomMapper2(); 21 var ccc = EmitMapperHelper.Instance.Convert<List<TestModelA>, List<TestModelB>>(modelAlist, conf); 22 23 stopwatch.Stop(); 24 string ok2 = string.Format(max + "次,EmitMapper 所用时间 :{0} 毫秒", stopwatch.ElapsedMilliseconds); 25 textBox1.AppendText(ok2 + " "); 26 27 return; 28 }
使用22次后,结果
1 方式/10万次采样 耗时/毫秒 2 手动生成 438 3 TinyMapper 549 4 EmitMapper 681 5 手动生成 428 6 TinyMapper 537 7 EmitMapper 709 8 手动生成 473 9 TinyMapper 534 10 EmitMapper 615 11 手动生成 463 12 TinyMapper 530 13 EmitMapper 617 14 手动生成 486 15 TinyMapper 550 16 EmitMapper 645 17 手动生成 465 18 TinyMapper 551 19 EmitMapper 654 20 手动生成 450 21 TinyMapper 541 22 EmitMapper 641 23 手动生成 442 24 TinyMapper 551 25 EmitMapper 674 26 手动生成 477 27 TinyMapper 543 28 EmitMapper 606 29 手动生成 458 30 TinyMapper 517 31 EmitMapper 584 32 手动生成 445 33 TinyMapper 512 34 EmitMapper 555 35 手动生成 456 36 TinyMapper 521 37 EmitMapper 580 38 手动生成 475 39 TinyMapper 550 40 EmitMapper 613 41 手动生成 523 42 TinyMapper 603 43 EmitMapper 673 44 手动生成 440 45 TinyMapper 500 46 EmitMapper 568 47 手动生成 457 48 TinyMapper 532 49 EmitMapper 607 50 手动生成 410 51 TinyMapper 472 52 EmitMapper 559 53 手动生成 477 54 TinyMapper 536 55 EmitMapper 596 56 手动生成 449 57 TinyMapper 521 58 EmitMapper 595 59 手动生成 488 60 TinyMapper 554 61 EmitMapper 640 62 手动生成 463 63 TinyMapper 520 64 EmitMapper 587 65 手动生成 432 66 TinyMapper 560 67 EmitMapper 605
个人使用总结:
tinyMapper 真的挺快的,EmitMapper 仅比其差了一点点而已(10万-1000万条数据中的映射场景并不多见,70多毫秒也不会太在意)。
因为EmitMapper的作者在2011年就不在维护了,我认为EmitMapper还是够吊的了。
但tinyMapper 刚出来不久,但性能真的是无与伦对的美丽!!赞,希望能作者能改善。
最后给出我心中,以上工具的打分和优点缺点简单评。