From ba13f0886f461a65d9841d2de0b59e152e6926c9 Mon Sep 17 00:00:00 2001 From: anisimovyuriy Date: Thu, 21 May 2015 17:34:31 +0200 Subject: [PATCH] Performance improvement for nested collections. Benchmarks for multiple mappers. Release 0.9.5 --- ExpressMapper NET40/TypeMapper.cs | 26 ++- PerformanceTest/Mapping/AutoMapperMapping.cs | 28 ++++ .../Mapping/ExpressMappingMapping.cs | 15 ++ .../Mapping/MapsterMapperMappings.cs | 37 +++++ PerformanceTest/Mapping/OoMapperMappings.cs | 39 +++++ PerformanceTest/Mapping/TinyMapperMappings.cs | 19 +++ .../Mapping/ValueInjectorMappings.cs | 75 +++++++++ PerformanceTest/PerformanceTest.csproj | 24 ++- PerformanceTest/Program.cs | 58 +++---- PerformanceTest/Tests/AdvancedTest.cs | 109 +++++++++++++ PerformanceTest/Tests/BaseTest.cs | 151 ++++++++++++++++-- PerformanceTest/Tests/BaseTestResult.cs | 64 ++++++++ PerformanceTest/Tests/ComplexTest.cs | 57 ++++++- PerformanceTest/Tests/SimpleStructTest.cs | 57 +++++++ PerformanceTest/Tests/SimpleTest.cs | 58 +++++++ .../Tests/SimpleWithAssociationTest.cs | 58 ++++++- .../Tests/SimpleWithCollectionTest.cs | 58 ++++++- .../{Tests => ViewModels}/NewsViewModel.cs | 2 +- PerformanceTest/ViewModels/TestViewModel.cs | 4 + PerformanceTest/packages.config | 4 + 20 files changed, 889 insertions(+), 54 deletions(-) create mode 100644 PerformanceTest/Mapping/MapsterMapperMappings.cs create mode 100644 PerformanceTest/Mapping/OoMapperMappings.cs create mode 100644 PerformanceTest/Mapping/TinyMapperMappings.cs create mode 100644 PerformanceTest/Mapping/ValueInjectorMappings.cs create mode 100644 PerformanceTest/Tests/AdvancedTest.cs create mode 100644 PerformanceTest/Tests/BaseTestResult.cs rename PerformanceTest/{Tests => ViewModels}/NewsViewModel.cs (88%) diff --git a/ExpressMapper NET40/TypeMapper.cs b/ExpressMapper NET40/TypeMapper.cs index 0f1399c..776d726 100644 --- a/ExpressMapper NET40/TypeMapper.cs +++ b/ExpressMapper NET40/TypeMapper.cs @@ -111,7 +111,7 @@ public List GetMapExpressions() public IList ProcessCollection(IEnumerable src) { var source = src as IEnumerable; - var destination = new List(); + var destination = new List(source.Count()); foreach (var item in source) { destination.Add(MapTo(item)); @@ -121,19 +121,24 @@ public IList ProcessCollection(IEnumerable src) public IEnumerable ProcessArray(IEnumerable src) { - var source = src as IEnumerable; - var destination = new List(); - foreach (var item in source) + var source = src as T[]; + var destination = new List(source.Length); + for (var i = 0; i < source.Length; i++) { - destination.Add(MapTo(item)); + destination.Add(MapTo(source[i])); } return destination.ToArray(); } public IQueryable ProcessQueryable(IEnumerable src) { - var enumerable = src as IEnumerable; - return enumerable.Select(MapTo).AsQueryable(); + var source = src as IEnumerable; + var destination = new List(source.Count()); + foreach (var item in source) + { + destination.Add(MapTo(item)); + } + return destination.AsQueryable(); } public void AfterMap(Action afterMap) @@ -315,7 +320,12 @@ private static BlockExpression MapCollection(Type sourcePropType, Type destpropT var destList = typeof(List<>).MakeGenericType(destType); var destColl = Expression.Variable(destList, string.Format("{0}_{1}", typeof(TN).Name, callSetPropMethod.Member.Name)); - var newColl = Expression.New(destList); + + var constructorInfo = destList.GetConstructors().First(c => c.GetParameters().FirstOrDefault(p => p.ParameterType == typeof(int)) != null); + + var srcCountExp = Expression.Call(typeof (Enumerable), "Count", new[] {sourceType}, sourceVariable); + + var newColl = Expression.New(constructorInfo, srcCountExp); var destAssign = Expression.Assign(destColl, newColl); var closedEnumeratorSourceType = typeof(IEnumerator<>).MakeGenericType(sourceType); diff --git a/PerformanceTest/Mapping/AutoMapperMapping.cs b/PerformanceTest/Mapping/AutoMapperMapping.cs index 1c082e2..d98dc86 100644 --- a/PerformanceTest/Mapping/AutoMapperMapping.cs +++ b/PerformanceTest/Mapping/AutoMapperMapping.cs @@ -35,5 +35,33 @@ public static void Init() Mapper.CreateMap(); } + + public static void InitAdvanced() + { + Mapper.Reset(); + Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.DefaultSharedOption, src => src.MapFrom(m => m.DefaultOption)); + Mapper.CreateMap() + .ForMember(dest => dest.Type, src => src.MapFrom(m => (Types) m.Type)) + .ForMember(dest => dest.Age, src => src.MapFrom(m => m.Age)) + .ForMember(dest => dest.Weight, src => src.MapFrom(m => m.Weight*2)) + .ForMember(dest => dest.Name, + src => src.MapFrom(m => string.Format("{0} - {1} - {2}", m.Name, m.Weight, m.Age))) + .ForMember(dest => dest.SpareTheProduct, src => src.MapFrom(m => m.SpareProduct)) + .ForMember(dest => dest.Description, src => src.MapFrom(m => string.Format("{0} - {1}", m.Name, m.Id))); + + Mapper.CreateMap(); + + Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.BelongTo, src => src.MapFrom(m => m.Role)); + + Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.OwnedArticles, src => src.ResolveUsing(m => m.Articles)); + + Mapper.CreateMap(); + } } } diff --git a/PerformanceTest/Mapping/ExpressMappingMapping.cs b/PerformanceTest/Mapping/ExpressMappingMapping.cs index 49f0fc3..2eb2f4e 100644 --- a/PerformanceTest/Mapping/ExpressMappingMapping.cs +++ b/PerformanceTest/Mapping/ExpressMappingMapping.cs @@ -35,5 +35,20 @@ public static void Init() Mapper.Register(); Mapper.Compile(); } + + public static void InitAdvanced() + { + Mapper.Register(); + Mapper.Register() + .Member(dest => dest.DefaultSharedOption, src => src.DefaultOption); + Mapper.Register() + .Member(dest => dest.Age, src => src.Age) + .Member(dest => dest.Weight, src => src.Weight * 2) + .Member(dest => dest.Type, src => (Types)src.Type) + .Member(dest => dest.Name, src => string.Format("{0} - {1} - {2}", src.Name, src.Weight, src.Age)) + .Member(dest => dest.SpareTheProduct, src => src.SpareProduct) + .Member(dest => dest.Description, src => string.Format("{0} - {1}", src.Name, src.Id)); + Mapper.Compile(); + } } } diff --git a/PerformanceTest/Mapping/MapsterMapperMappings.cs b/PerformanceTest/Mapping/MapsterMapperMappings.cs new file mode 100644 index 0000000..f601522 --- /dev/null +++ b/PerformanceTest/Mapping/MapsterMapperMappings.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using Mapster; +using PerformanceTest.Enums; +using PerformanceTest.Models; +using PerformanceTest.ViewModels; + +namespace PerformanceTest.Mapping +{ + public class MapsterMapperMappings + { + public static void Init() + { + TypeAdapterConfig + .NewConfig() + .Map(dest => dest.DefaultSharedOption, src => TypeAdapter.Adapt(src.DefaultOption)); + + TypeAdapterConfig + .NewConfig() + .Map(dest => dest.Age, src => src.Age) + .Map(dest => dest.Weight, src => src.Weight * 2) + .Map(dest => dest.Type, src => (Types)src.Type) + .Map(dest => dest.Name, src => string.Format("{0} - {1} - {2}", src.Name, src.Weight, src.Age)) + .Map(dest => dest.Name, src => string.Format("{0} - {1} - {2}", src.Name, src.Weight, src.Age)) + .Map(dest => dest.SpareTheProduct, src => TypeAdapter.Adapt(src.SpareProduct)) + .Map(dest => dest.Description, src => string.Format("{0} - {1}", src.Name, src.Id)); + + TypeAdapterConfig + .NewConfig() + .Map(dest => dest.BelongTo, src => TypeAdapter.Adapt(src.Role)); + + + TypeAdapterConfig + .NewConfig() + .Map(dest => dest.OwnedArticles, src => TypeAdapter.Adapt, ArticleViewModel[]>(src.Articles)); + } + } +} diff --git a/PerformanceTest/Mapping/OoMapperMappings.cs b/PerformanceTest/Mapping/OoMapperMappings.cs new file mode 100644 index 0000000..ee4fcdc --- /dev/null +++ b/PerformanceTest/Mapping/OoMapperMappings.cs @@ -0,0 +1,39 @@ +using OoMapper; +using PerformanceTest.Enums; +using PerformanceTest.Models; +using PerformanceTest.Tests; +using PerformanceTest.ViewModels; + +namespace PerformanceTest.Mapping +{ + public class OoMapperMappings + { + public static void Init() + { + Mapper.Reset(); + Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.DefaultSharedOption, src => src.MapFrom(m => m.DefaultOption)); + Mapper.CreateMap() + .ForMember(dest => dest.Weight, opt => opt.MapFrom(src => src.Weight * 2)) + .ForMember(dest => dest.Age, opt => opt.MapFrom(src => src.Age)) + .ForMember(dest => dest.Type, src => src.MapFrom(m => (Types)m.Type)) + .ForMember(dest => dest.Name, src => src.MapFrom(m => string.Format("{0} - {1} - {2}", m.Name, m.Weight, m.Age))) + .ForMember(dest => dest.SpareTheProduct, opt => opt.MapFrom(src => src.SpareProduct)) + .ForMember(dest => dest.Description, opt => opt.MapFrom(src => string.Format("{0} - {1}", src.Name, src.Id))) + .ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.Products)); + + Mapper.CreateMap(); + + Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.BelongTo, src => src.MapFrom(m => m.Role)); + + Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.OwnedArticles, src => src.MapFrom(m => m.Articles)); + + Mapper.CreateMap(); + } + } +} diff --git a/PerformanceTest/Mapping/TinyMapperMappings.cs b/PerformanceTest/Mapping/TinyMapperMappings.cs new file mode 100644 index 0000000..56bf2f2 --- /dev/null +++ b/PerformanceTest/Mapping/TinyMapperMappings.cs @@ -0,0 +1,19 @@ +using Nelibur.ObjectMapper; +using PerformanceTest.Models; +using PerformanceTest.Tests; +using PerformanceTest.ViewModels; + +namespace PerformanceTest.Mapping +{ + public class TinyMapperMappings + { + public static void Init() + { + TinyMapper.Bind(); + + TinyMapper.Bind(); + + TinyMapper.Bind(); + } + } +} diff --git a/PerformanceTest/Mapping/ValueInjectorMappings.cs b/PerformanceTest/Mapping/ValueInjectorMappings.cs new file mode 100644 index 0000000..ac165ec --- /dev/null +++ b/PerformanceTest/Mapping/ValueInjectorMappings.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Omu.ValueInjecter; +using PerformanceTest.Enums; +using PerformanceTest.Models; +using PerformanceTest.ViewModels; + +namespace PerformanceTest.Mapping +{ + public class ValueInjectorMappings + { + public static void Init() + { + Mapper.Reset(); + + Mapper.AddMap(src => + { + var productViewModel = new ProductViewModel(); + productViewModel.InjectFrom(src); + productViewModel.DefaultSharedOption = + Mapper.Map(src.DefaultOption); + productViewModel.Options = new List(); + foreach (var pv in src.Options) + { + productViewModel.Options.Add(Mapper.Map(pv)); + } + return productViewModel; + }); + + Mapper.AddMap(src => + { + var testViewModel = new TestViewModel(string.Format("{0} - {1}", src.Name, src.Id)); + testViewModel.InjectFrom(src); + + testViewModel.Name = string.Format("{0} - {1} - {2}", src.Name, src.Weight, src.Age); + + testViewModel.Product = Mapper.Map(src.Product); + testViewModel.SpareTheProduct = Mapper.Map(src.SpareProduct); + testViewModel.Type = (Types) src.Type; + testViewModel.Weight = src.Weight*2; + testViewModel.Products = new List(); + foreach (var product in src.Products) + { + testViewModel.Products.Add(Mapper.Map(product)); + } + return testViewModel; + }); + + Mapper.AddMap(src => + { + var userViewModel = new UserViewModel(); + userViewModel.InjectFrom(src); + userViewModel.BelongTo = Mapper.Map(src.Role); + return userViewModel; + }); + + Mapper.AddMap(src => + { + var articles = new ArticleViewModel[src.Articles.Count()]; + var authorViewModel = new AuthorViewModel(); + authorViewModel.InjectFrom(src); + + for (var i = 0; i < articles.Length; i++) + { + articles[i] = Mapper.Map(src.Articles.ElementAt(i)); + } + authorViewModel.OwnedArticles = articles; + return authorViewModel; + }); + } + } +} diff --git a/PerformanceTest/PerformanceTest.csproj b/PerformanceTest/PerformanceTest.csproj index c7e5c79..9960a34 100644 --- a/PerformanceTest/PerformanceTest.csproj +++ b/PerformanceTest/PerformanceTest.csproj @@ -42,6 +42,18 @@ ..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll + + ..\packages\Mapster.1.14.0.0\lib\net45\Mapster.dll + True + + + ..\packages\ValueInjecter.3.0.1.1\lib\net45\Omu.ValueInjecter.dll + True + + + ..\packages\OoMapper.0.2.0.33\lib\net4\OoMapper.dll + True + @@ -49,13 +61,21 @@ + + ..\packages\TinyMapper.1.0.18\lib\net45\TinyMapper.dll + True + + + + + @@ -67,10 +87,12 @@ + + - + diff --git a/PerformanceTest/Program.cs b/PerformanceTest/Program.cs index 5f5b70a..a17a41a 100644 --- a/PerformanceTest/Program.cs +++ b/PerformanceTest/Program.cs @@ -1,6 +1,8 @@ using System; using System.Threading; +using PerformanceTest.Models; using PerformanceTest.Tests; +using PerformanceTest.ViewModels; namespace PerformanceTest { @@ -12,84 +14,84 @@ static void Main(string[] args) simpleStructTest.RunTest(100000); simpleStructTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); + simpleStructTest.RunTest(500000); + simpleStructTest.PrintResults(); simpleStructTest.RunTest(1000000); simpleStructTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); - + GC.Collect(2); + Thread.Sleep(1000); var simpleTest = new SimpleTest(); simpleTest.RunTest(100000); simpleTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); - simpleTest.RunTest(1000000); simpleTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); - simpleTest.RunTest(5000000); + simpleTest.RunTest(3000000); simpleTest.PrintResults(); + GC.Collect(2); - Thread.Sleep(3); + Thread.Sleep(1000); var simpleAssociationTest = new SimpleWithAssociationTest(); simpleAssociationTest.RunTest(100000); simpleAssociationTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); + simpleAssociationTest.RunTest(500000); + simpleAssociationTest.PrintResults(); simpleAssociationTest.RunTest(1000000); simpleAssociationTest.PrintResults(); GC.Collect(2); - Thread.Sleep(3); - + Thread.Sleep(1000); var simpleCollectionTest = new SimpleWithCollectionTest(); simpleCollectionTest.RunTest(10000); simpleCollectionTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); + simpleCollectionTest.RunTest(50000); + simpleCollectionTest.PrintResults(); simpleCollectionTest.RunTest(100000); simpleCollectionTest.PrintResults(); GC.Collect(2); - Thread.Sleep(3); + Thread.Sleep(1000); + + + var advancedTest = new AdvancedTest(); + advancedTest.RunTest(10000); + advancedTest.PrintResults(); + + advancedTest.RunTest(100000); + advancedTest.PrintResults(); + + advancedTest.RunTest(200000); + advancedTest.PrintResults(); + GC.Collect(2); + Thread.Sleep(1000); var complexTest = new ComplexTest(); complexTest.RunTest(10000); complexTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); - complexTest.RunTest(100000); complexTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); - - complexTest.RunTest(400000); + complexTest.RunTest(200000); complexTest.PrintResults(); - GC.Collect(2); - Thread.Sleep(3); + BaseTestResult.FormatResults(); Console.ReadLine(); } diff --git a/PerformanceTest/Tests/AdvancedTest.cs b/PerformanceTest/Tests/AdvancedTest.cs new file mode 100644 index 0000000..ca4191f --- /dev/null +++ b/PerformanceTest/Tests/AdvancedTest.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using Mapster; +using PerformanceTest.Generators; +using PerformanceTest.Mapping; +using PerformanceTest.Models; +using PerformanceTest.ViewModels; + +namespace PerformanceTest.Tests +{ + public class AdvancedTest : BaseTest, List> + { + protected override List GetData() + { + return DataGenerator.GetTests(Count); + } + + protected override void InitAutoMapper() + { + AutoMapperMapping.Init(); + } + + protected override void InitExpressMapper() + { + ExpressMapperMapping.InitAdvanced(); + } + + protected override void InitOoMapper() + { + OoMapperMappings.Init(); + } + + protected override void InitValueInjectorMapper() + { + ValueInjectorMappings.Init(); + } + + protected override void InitMapsterMapper() + { + MapsterMapperMappings.Init(); + } + + protected override void InitTinyMapper() + { + TinyMapperMappings.Init(); + } + + protected override void InitNativeMapper() + { + } + + protected override List AutoMapperMap(List src) + { + return AutoMapper.Mapper.Map, List>(src); + } + + protected override List ExpressMapperMap(List src) + { + return ExpressMapper.Mapper.Map, List>(src); + } + + protected override List OoMapperMap(List src) + { + var testViewModels = OoMapper.Mapper.Map, List>(src); + return testViewModels; + } + + protected override List ValueInjectorMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(Omu.ValueInjecter.Mapper.Map(item)); + } + return list; + } + + protected override List MapsterMap(List src) + { + var testViewModels = TypeAdapter.Adapt, List>(src); + return testViewModels; + } + + protected override List TinyMapperMap(List src) + { + throw new NotImplementedException(); + } + + protected override List NativeMapperMap(List src) + { + var list = new List(); + foreach (var test in src) + { + list.Add(NativeMapping.Map(test)); + } + return list; + } + + protected override string TestName + { + get { return "AdvancedTest"; } + } + + protected override string Size + { + get { return "XL"; } + } + } +} diff --git a/PerformanceTest/Tests/BaseTest.cs b/PerformanceTest/Tests/BaseTest.cs index 5125b60..b0a3c51 100644 --- a/PerformanceTest/Tests/BaseTest.cs +++ b/PerformanceTest/Tests/BaseTest.cs @@ -1,55 +1,132 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace PerformanceTest.Tests { - public abstract class BaseTest : ITest + public abstract class BaseTest : BaseTestResult, ITest { - protected int Count { set; get; } private Stopwatch AutoMapperStopwatch { get; set; } private Stopwatch ExpressMapperStopwatch { get; set; } private Stopwatch NativeMapperStopwatch { get; set; } + private Stopwatch OoMapperStopwatch { get; set; } + private Stopwatch ValueInjectorStopwatch { get; set; } + private Stopwatch MapsterStopwatch { get; set; } + private Stopwatch TinyStopwatch { get; set; } public void RunTest(int count) { + AutoMapperStopwatch = new Stopwatch(); + ExpressMapperStopwatch = new Stopwatch(); + NativeMapperStopwatch = new Stopwatch(); + OoMapperStopwatch = new Stopwatch(); + ValueInjectorStopwatch = new Stopwatch(); + MapsterStopwatch = new Stopwatch(); + TinyStopwatch = new Stopwatch(); + Count = count; InitAutoMapper(); InitExpressMapper(); + InitOoMapper(); InitNativeMapper(); + InitValueInjectorMapper(); + InitMapsterMapper(); + InitTinyMapper(); Console.WriteLine("Mapping initialization finished"); var src = GetData(); - AutoMapperStopwatch = Stopwatch.StartNew(); - AutoMapperMap(src); - AutoMapperStopwatch.Stop(); - Console.WriteLine("Automapper mapping has been finished"); + ExpressMapperStopwatch = Stopwatch.StartNew(); + ExpressMapperMap(src); + ExpressMapperStopwatch.Stop(); + Console.WriteLine("Expressmapper mapping has been finished"); NativeMapperStopwatch = Stopwatch.StartNew(); NativeMapperMap(src); NativeMapperStopwatch.Stop(); Console.WriteLine("Native mapping has been finished"); - ExpressMapperStopwatch = Stopwatch.StartNew(); - ExpressMapperMap(src); - ExpressMapperStopwatch.Stop(); - Console.WriteLine("Expressmapper mapping has been finished"); + try + { + OoMapperStopwatch = Stopwatch.StartNew(); + OoMapperMap(src); + OoMapperStopwatch.Stop(); + } + catch (Exception ex) + { + OoMapperStopwatch.Stop(); + OoMapperStopwatch.Reset(); + Console.WriteLine("OoMapper has thrown expception!"); + } + Console.WriteLine("OoMapper mapping has been finished"); + + try + { + ValueInjectorStopwatch = Stopwatch.StartNew(); + ValueInjectorMap(src); + ValueInjectorStopwatch.Stop(); + } + catch (Exception ex) + { + ValueInjectorStopwatch.Stop(); + ValueInjectorStopwatch.Reset(); + Console.WriteLine("ValueInjector has thrown expception!"); + } + + try + { + MapsterStopwatch = Stopwatch.StartNew(); + MapsterMap(src); + MapsterStopwatch.Stop(); + } + catch (Exception ex) + { + MapsterStopwatch.Stop(); + MapsterStopwatch.Reset(); + Console.WriteLine("Mapster has thrown expception!"); + } + Console.WriteLine("Mapster mapping has been finished"); + + try + { + TinyStopwatch = Stopwatch.StartNew(); + TinyMapperMap(src); + TinyStopwatch.Stop(); + } + catch (Exception ex) + { + TinyStopwatch.Stop(); + TinyStopwatch.Reset(); + Console.WriteLine("Tinymapper has thrown expception!"); + } + Console.WriteLine("Tinymapper mapping has been finished"); + + AutoMapperStopwatch = Stopwatch.StartNew(); + AutoMapperMap(src); + AutoMapperStopwatch.Stop(); + Console.WriteLine("Automapper mapping has been finished"); } protected abstract T GetData(); protected abstract void InitAutoMapper(); protected abstract void InitExpressMapper(); + protected abstract void InitOoMapper(); + protected abstract void InitValueInjectorMapper(); + protected abstract void InitMapsterMapper(); + protected abstract void InitTinyMapper(); protected abstract void InitNativeMapper(); protected abstract TN AutoMapperMap(T src); protected abstract TN ExpressMapperMap(T src); + protected abstract TN OoMapperMap(T src); + protected abstract TN ValueInjectorMap(T src); + protected abstract TN MapsterMap(T src); + protected abstract TN TinyMapperMap(T src); protected abstract TN NativeMapperMap(T src); - protected abstract string TestName { get; } + //protected abstract string TestName { get; } + //protected abstract string Size { get; } public void RunTestManualForEach(int count) { @@ -64,8 +141,56 @@ public void PrintResults() Console.WriteLine("Test results for {0} for collection size of {1}", TestName, Count); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Automapper took {0} ms.", AutoMapperStopwatch.ElapsedMilliseconds); + AddResults("auto", Count, (int)AutoMapperStopwatch.ElapsedMilliseconds); Console.WriteLine("Expressmapper took {0} ms.", ExpressMapperStopwatch.ElapsedMilliseconds); + AddResults("express", Count, (int)ExpressMapperStopwatch.ElapsedMilliseconds); + if (OoMapperStopwatch.ElapsedMilliseconds == 0) + { + Console.WriteLine("Oomapper - not supported mapping"); + AddResults("oomapper", Count, -1); + } + else + { + Console.WriteLine("Oomapper took {0} ms.", OoMapperStopwatch.ElapsedMilliseconds); + AddResults("oomapper", Count, (int)OoMapperStopwatch.ElapsedMilliseconds); + } + + if (ValueInjectorStopwatch.ElapsedMilliseconds == 0) + { + Console.WriteLine("ValueInjector - not supported mapping"); + AddResults("valueinjecter", Count, -1); + } + else + { + Console.WriteLine("ValueInjector took {0} ms.", ValueInjectorStopwatch.ElapsedMilliseconds); + AddResults("valueinjecter", Count, (int)ValueInjectorStopwatch.ElapsedMilliseconds); + } + + + if (MapsterStopwatch.ElapsedMilliseconds == 0) + { + Console.WriteLine("Mapster - not supported mapping"); + AddResults("mapster", Count, -1); + } + else + { + Console.WriteLine("Mapster took {0} ms.", MapsterStopwatch.ElapsedMilliseconds); + AddResults("mapster", Count, (int)MapsterStopwatch.ElapsedMilliseconds); + } + + if (TinyStopwatch.ElapsedMilliseconds == 0) + { + Console.WriteLine("Tinymapper - not supported mapping"); + AddResults("tiny", Count, -1); + } + else + { + Console.WriteLine("Tinymapper took {0} ms.", TinyStopwatch.ElapsedMilliseconds); + AddResults("tiny", Count, (int)TinyStopwatch.ElapsedMilliseconds); + } + Console.WriteLine("Native code mapping took {0} ms.", NativeMapperStopwatch.ElapsedMilliseconds); + AddResults("native", Count, (int)NativeMapperStopwatch.ElapsedMilliseconds); Console.WriteLine(); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.Gray; diff --git a/PerformanceTest/Tests/BaseTestResult.cs b/PerformanceTest/Tests/BaseTestResult.cs new file mode 100644 index 0000000..d1483f0 --- /dev/null +++ b/PerformanceTest/Tests/BaseTestResult.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PerformanceTest.Tests +{ + public abstract class BaseTestResult + { + public static Dictionary>> StructuredResults = new Dictionary>>(); + protected abstract string TestName { get; } + protected abstract string Size { get; } + protected int Count { set; get; } + + protected void AddResults(string mapper, int qty, int ms) + { + if (!StructuredResults.ContainsKey(Size)) + { + StructuredResults.Add(Size, new Dictionary>()); + } + + if (!StructuredResults[Size].ContainsKey(mapper)) + { + StructuredResults[Size].Add(mapper, new Dictionary()); + } + + StructuredResults[Size][mapper][qty] = ms; + } + + public static void FormatResults() + { + Console.WriteLine("-----------------------------------------------------------------------"); + Console.WriteLine("FormattedResults"); + + foreach (var structuredResult in StructuredResults) + { + Console.WriteLine("{0} : {{", structuredResult.Key); + var qty = new StringBuilder(); + foreach (var result in structuredResult.Value) + { + foreach (var res in result.Value) + { + qty.Append(string.Format("'{0}k',", res.Key / 1000)); + } + break; + } + var qt = qty.ToString(); + qt = qt.Remove(qt.LastIndexOf(",", System.StringComparison.Ordinal), 1); + Console.WriteLine(" qty : [{0}],", qt); + foreach (var result in structuredResult.Value) + { + var mapperVals = new StringBuilder(); + foreach (var res in result.Value) + { + mapperVals.Append(string.Format("{0},", res.Value)); + } + var mapper = mapperVals.ToString(); + mapper = mapper.Remove(mapper.LastIndexOf(",", System.StringComparison.Ordinal), 1); + Console.WriteLine(" {0} : [{1}],", result.Key, mapper); + } + Console.WriteLine("},"); + } + } + } +} diff --git a/PerformanceTest/Tests/ComplexTest.cs b/PerformanceTest/Tests/ComplexTest.cs index 9ea415f..eb62738 100644 --- a/PerformanceTest/Tests/ComplexTest.cs +++ b/PerformanceTest/Tests/ComplexTest.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using Mapster; using PerformanceTest.Generators; using PerformanceTest.Mapping; using PerformanceTest.Models; @@ -23,6 +25,26 @@ protected override void InitExpressMapper() ExpressMapperMapping.Init(); } + protected override void InitOoMapper() + { + OoMapperMappings.Init(); + } + + protected override void InitValueInjectorMapper() + { + ValueInjectorMappings.Init(); + } + + protected override void InitMapsterMapper() + { + MapsterMapperMappings.Init(); + } + + protected override void InitTinyMapper() + { + TinyMapperMappings.Init(); + } + protected override void InitNativeMapper() { } @@ -37,6 +59,34 @@ protected override List ExpressMapperMap(List src) return ExpressMapper.Mapper.Map, List>(src); } + protected override List OoMapperMap(List src) + { + // Custom constructor, beforeMap, AfterMap is not supported + + throw new NotImplementedException(); + //return OoMapper.Mapper.Map, List>(src); + } + + protected override List ValueInjectorMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(Omu.ValueInjecter.Mapper.Map(item)); + } + return list; + } + + protected override List MapsterMap(List src) + { + return TypeAdapter.Adapt, List>(src); + } + + protected override List TinyMapperMap(List src) + { + throw new NotImplementedException(); + } + protected override List NativeMapperMap(List src) { var list = new List(); @@ -51,5 +101,10 @@ protected override string TestName { get { return "ComplexTest"; } } + + protected override string Size + { + get { return "XXL"; } + } } } diff --git a/PerformanceTest/Tests/SimpleStructTest.cs b/PerformanceTest/Tests/SimpleStructTest.cs index 0973803..5a30558 100644 --- a/PerformanceTest/Tests/SimpleStructTest.cs +++ b/PerformanceTest/Tests/SimpleStructTest.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using Mapster; +using Nelibur.ObjectMapper; using PerformanceTest.Generators; using PerformanceTest.Mapping; using PerformanceTest.Models; @@ -24,6 +26,26 @@ protected override void InitExpressMapper() ExpressMapperMapping.Init(); } + protected override void InitOoMapper() + { + OoMapperMappings.Init(); + } + + protected override void InitValueInjectorMapper() + { + ValueInjectorMappings.Init(); + } + + protected override void InitMapsterMapper() + { + MapsterMapperMappings.Init(); + } + + protected override void InitTinyMapper() + { + TinyMapperMappings.Init(); + } + protected override void InitNativeMapper() { } @@ -38,6 +60,36 @@ protected override List ExpressMapperMap(List src) return ExpressMapper.Mapper.Map, List>(src); } + protected override List OoMapperMap(List src) + { + return OoMapper.Mapper.Map, List>(src); + } + + protected override List ValueInjectorMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(Omu.ValueInjecter.Mapper.Map(item)); + } + return list; + } + + protected override List MapsterMap(List src) + { + return TypeAdapter.Adapt, List>(src); + } + + protected override List TinyMapperMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(TinyMapper.Map(item)); + } + return list; + } + protected override List NativeMapperMap(List src) { var result = new List(); @@ -52,5 +104,10 @@ protected override string TestName { get { return "SimpleStructTest"; } } + + protected override string Size + { + get { return "XS"; } + } } } diff --git a/PerformanceTest/Tests/SimpleTest.cs b/PerformanceTest/Tests/SimpleTest.cs index ce43c01..4e5ebc7 100644 --- a/PerformanceTest/Tests/SimpleTest.cs +++ b/PerformanceTest/Tests/SimpleTest.cs @@ -1,7 +1,10 @@ using System.Collections.Generic; +using Mapster; +using Nelibur.ObjectMapper; using PerformanceTest.Generators; using PerformanceTest.Mapping; using PerformanceTest.Models; +using PerformanceTest.ViewModels; namespace PerformanceTest.Tests { @@ -22,6 +25,26 @@ protected override void InitExpressMapper() ExpressMapperMapping.Init(); } + protected override void InitOoMapper() + { + OoMapperMappings.Init(); + } + + protected override void InitValueInjectorMapper() + { + ValueInjectorMappings.Init(); + } + + protected override void InitMapsterMapper() + { + MapsterMapperMappings.Init(); + } + + protected override void InitTinyMapper() + { + TinyMapperMappings.Init(); + } + protected override void InitNativeMapper() { } @@ -36,6 +59,36 @@ protected override List ExpressMapperMap(List src) return ExpressMapper.Mapper.Map, List>(src); } + protected override List OoMapperMap(List src) + { + return OoMapper.Mapper.Map, List>(src); + } + + protected override List ValueInjectorMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(Omu.ValueInjecter.Mapper.Map(item)); + } + return list; + } + + protected override List MapsterMap(List src) + { + return TypeAdapter.Adapt, List>(src); + } + + protected override List TinyMapperMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(TinyMapper.Map(item)); + } + return list; + } + protected override List NativeMapperMap(List src) { var result = new List(); @@ -50,5 +103,10 @@ protected override string TestName { get { return "SimpleTest"; } } + + protected override string Size + { + get { return "S"; } + } } } diff --git a/PerformanceTest/Tests/SimpleWithAssociationTest.cs b/PerformanceTest/Tests/SimpleWithAssociationTest.cs index 2177d8d..e7a1f6b 100644 --- a/PerformanceTest/Tests/SimpleWithAssociationTest.cs +++ b/PerformanceTest/Tests/SimpleWithAssociationTest.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using Mapster; +using Nelibur.ObjectMapper; using PerformanceTest.Generators; using PerformanceTest.Mapping; using PerformanceTest.Models; @@ -23,6 +26,26 @@ protected override void InitExpressMapper() ExpressMapperMapping.Init(); } + protected override void InitOoMapper() + { + OoMapperMappings.Init(); + } + + protected override void InitValueInjectorMapper() + { + ValueInjectorMappings.Init(); + } + + protected override void InitMapsterMapper() + { + MapsterMapperMappings.Init(); + } + + protected override void InitTinyMapper() + { + TinyMapperMappings.Init(); + } + protected override void InitNativeMapper() { } @@ -37,6 +60,34 @@ protected override List ExpressMapperMap(List src) return ExpressMapper.Mapper.Map, List>(src); } + protected override List OoMapperMap(List src) + { + var userViewModels = OoMapper.Mapper.Map, List>(src); + return userViewModels; + } + + protected override List ValueInjectorMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(Omu.ValueInjecter.Mapper.Map(item)); + } + return list; + } + + protected override List MapsterMap(List src) + { + var userViewModels = TypeAdapter.Adapt, List>(src); + return userViewModels; + } + + protected override List TinyMapperMap(List src) + { + // custom mapping is not supported + throw new NotImplementedException(); + } + protected override List NativeMapperMap(List src) { var result = new List(); @@ -51,5 +102,10 @@ protected override string TestName { get { return "SimpleWithAssociationTest"; } } + + protected override string Size + { + get { return "M"; } + } } } diff --git a/PerformanceTest/Tests/SimpleWithCollectionTest.cs b/PerformanceTest/Tests/SimpleWithCollectionTest.cs index 41a5029..49a9015 100644 --- a/PerformanceTest/Tests/SimpleWithCollectionTest.cs +++ b/PerformanceTest/Tests/SimpleWithCollectionTest.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using Mapster; +using Nelibur.ObjectMapper; using PerformanceTest.Generators; using PerformanceTest.Mapping; using PerformanceTest.Models; @@ -23,6 +26,26 @@ protected override void InitExpressMapper() ExpressMapperMapping.Init(); } + protected override void InitOoMapper() + { + OoMapperMappings.Init(); + } + + protected override void InitValueInjectorMapper() + { + ValueInjectorMappings.Init(); + } + + protected override void InitMapsterMapper() + { + MapsterMapperMappings.Init(); + } + + protected override void InitTinyMapper() + { + TinyMapperMappings.Init(); + } + protected override void InitNativeMapper() { } @@ -37,6 +60,34 @@ protected override List ExpressMapperMap(List src) return ExpressMapper.Mapper.Map, List>(src); } + protected override List OoMapperMap(List src) + { + var authorViewModels = OoMapper.Mapper.Map, List>(src); + return authorViewModels; + } + + protected override List ValueInjectorMap(List src) + { + var list = new List(); + foreach (var item in src) + { + list.Add(Omu.ValueInjecter.Mapper.Map(item)); + } + return list; + } + + protected override List MapsterMap(List src) + { + var authorViewModels = TypeAdapter.Adapt, List>(src); + return authorViewModels; + } + + protected override List TinyMapperMap(List src) + { + // custom mapping is not supported + throw new NotImplementedException(); + } + protected override List NativeMapperMap(List src) { var result = new List(); @@ -51,5 +102,10 @@ protected override string TestName { get { return "SimpleWithCollectionTest"; } } + + protected override string Size + { + get { return "L"; } + } } } diff --git a/PerformanceTest/Tests/NewsViewModel.cs b/PerformanceTest/ViewModels/NewsViewModel.cs similarity index 88% rename from PerformanceTest/Tests/NewsViewModel.cs rename to PerformanceTest/ViewModels/NewsViewModel.cs index dc2c602..2e0306f 100644 --- a/PerformanceTest/Tests/NewsViewModel.cs +++ b/PerformanceTest/ViewModels/NewsViewModel.cs @@ -1,6 +1,6 @@ using System; -namespace PerformanceTest.Tests +namespace PerformanceTest.ViewModels { public class NewsViewModel { diff --git a/PerformanceTest/ViewModels/TestViewModel.cs b/PerformanceTest/ViewModels/TestViewModel.cs index 81defe2..d9ebc44 100644 --- a/PerformanceTest/ViewModels/TestViewModel.cs +++ b/PerformanceTest/ViewModels/TestViewModel.cs @@ -6,6 +6,10 @@ namespace PerformanceTest.ViewModels { public class TestViewModel { + public TestViewModel() + { + + } public TestViewModel(string descr) { Description = descr; diff --git a/PerformanceTest/packages.config b/PerformanceTest/packages.config index c3952de..0fc7901 100644 --- a/PerformanceTest/packages.config +++ b/PerformanceTest/packages.config @@ -1,4 +1,8 @@  + + + + \ No newline at end of file