Skip to content

Commit

Permalink
Performance improvement for nested collections. Benchmarks for multip…
Browse files Browse the repository at this point in the history
…le mappers. Release 0.9.5
  • Loading branch information
anisimovyuriy committed May 21, 2015
1 parent 6d47867 commit ba13f08
Show file tree
Hide file tree
Showing 20 changed files with 889 additions and 54 deletions.
26 changes: 18 additions & 8 deletions ExpressMapper NET40/TypeMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public List<Expression> GetMapExpressions()
public IList ProcessCollection(IEnumerable src)
{
var source = src as IEnumerable<T>;
var destination = new List<TN>();
var destination = new List<TN>(source.Count());
foreach (var item in source)
{
destination.Add(MapTo(item));
Expand All @@ -121,19 +121,24 @@ public IList ProcessCollection(IEnumerable src)

public IEnumerable ProcessArray(IEnumerable src)
{
var source = src as IEnumerable<T>;
var destination = new List<TN>();
foreach (var item in source)
var source = src as T[];
var destination = new List<TN>(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<T>;
return enumerable.Select(MapTo).AsQueryable();
var source = src as IEnumerable<T>;
var destination = new List<TN>(source.Count());
foreach (var item in source)
{
destination.Add(MapTo(item));
}
return destination.AsQueryable();
}

public void AfterMap(Action<T, TN> afterMap)
Expand Down Expand Up @@ -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);
Expand Down
28 changes: 28 additions & 0 deletions PerformanceTest/Mapping/AutoMapperMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,33 @@ public static void Init()

Mapper.CreateMap<Item, ItemViewModel>();
}

public static void InitAdvanced()
{
Mapper.Reset();
Mapper.CreateMap<ProductVariant, ProductVariantViewModel>();
Mapper.CreateMap<Product, ProductViewModel>()
.ForMember(dest => dest.DefaultSharedOption, src => src.MapFrom(m => m.DefaultOption));
Mapper.CreateMap<Test, TestViewModel>()
.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<News, NewsViewModel>();

Mapper.CreateMap<Role, RoleViewModel>();
Mapper.CreateMap<User, UserViewModel>()
.ForMember(dest => dest.BelongTo, src => src.MapFrom(m => m.Role));

Mapper.CreateMap<Article, ArticleViewModel>();
Mapper.CreateMap<Author, AuthorViewModel>()
.ForMember(dest => dest.OwnedArticles, src => src.ResolveUsing(m => m.Articles));

Mapper.CreateMap<Item, ItemViewModel>();
}
}
}
15 changes: 15 additions & 0 deletions PerformanceTest/Mapping/ExpressMappingMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,20 @@ public static void Init()
Mapper.Register<Item, ItemViewModel>();
Mapper.Compile();
}

public static void InitAdvanced()
{
Mapper.Register<ProductVariant, ProductVariantViewModel>();
Mapper.Register<Product, ProductViewModel>()
.Member(dest => dest.DefaultSharedOption, src => src.DefaultOption);
Mapper.Register<Test, TestViewModel>()
.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();
}
}
}
37 changes: 37 additions & 0 deletions PerformanceTest/Mapping/MapsterMapperMappings.cs
Original file line number Diff line number Diff line change
@@ -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<Product, ProductViewModel>
.NewConfig()
.Map(dest => dest.DefaultSharedOption, src => TypeAdapter.Adapt<ProductVariant, ProductVariantViewModel>(src.DefaultOption));

TypeAdapterConfig<Test, TestViewModel>
.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<Product, ProductViewModel>(src.SpareProduct))
.Map(dest => dest.Description, src => string.Format("{0} - {1}", src.Name, src.Id));

TypeAdapterConfig<User, UserViewModel>
.NewConfig()
.Map(dest => dest.BelongTo, src => TypeAdapter.Adapt<Role, RoleViewModel>(src.Role));


TypeAdapterConfig<Author, AuthorViewModel>
.NewConfig()
.Map(dest => dest.OwnedArticles, src => TypeAdapter.Adapt<IEnumerable<Article>, ArticleViewModel[]>(src.Articles));
}
}
}
39 changes: 39 additions & 0 deletions PerformanceTest/Mapping/OoMapperMappings.cs
Original file line number Diff line number Diff line change
@@ -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<ProductVariant, ProductVariantViewModel>();
Mapper.CreateMap<Product, ProductViewModel>()
.ForMember(dest => dest.DefaultSharedOption, src => src.MapFrom(m => m.DefaultOption));
Mapper.CreateMap<Test, TestViewModel>()
.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<News, NewsViewModel>();

Mapper.CreateMap<Role, RoleViewModel>();
Mapper.CreateMap<User, UserViewModel>()
.ForMember(dest => dest.BelongTo, src => src.MapFrom(m => m.Role));

Mapper.CreateMap<Article, ArticleViewModel>();
Mapper.CreateMap<Author, AuthorViewModel>()
.ForMember(dest => dest.OwnedArticles, src => src.MapFrom(m => m.Articles));

Mapper.CreateMap<Item, ItemViewModel>();
}
}
}
19 changes: 19 additions & 0 deletions PerformanceTest/Mapping/TinyMapperMappings.cs
Original file line number Diff line number Diff line change
@@ -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<ProductVariant, ProductVariantViewModel>();

TinyMapper.Bind<News, NewsViewModel>();

TinyMapper.Bind<Item, ItemViewModel>();
}
}
}
75 changes: 75 additions & 0 deletions PerformanceTest/Mapping/ValueInjectorMappings.cs
Original file line number Diff line number Diff line change
@@ -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<Product, ProductViewModel>(src =>
{
var productViewModel = new ProductViewModel();
productViewModel.InjectFrom(src);
productViewModel.DefaultSharedOption =
Mapper.Map<ProductVariant, ProductVariantViewModel>(src.DefaultOption);
productViewModel.Options = new List<ProductVariantViewModel>();
foreach (var pv in src.Options)
{
productViewModel.Options.Add(Mapper.Map<ProductVariant, ProductVariantViewModel>(pv));
}
return productViewModel;
});

Mapper.AddMap<Test, TestViewModel>(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<Product, ProductViewModel>(src.Product);
testViewModel.SpareTheProduct = Mapper.Map<Product, ProductViewModel>(src.SpareProduct);
testViewModel.Type = (Types) src.Type;
testViewModel.Weight = src.Weight*2;
testViewModel.Products = new List<ProductViewModel>();
foreach (var product in src.Products)
{
testViewModel.Products.Add(Mapper.Map<Product, ProductViewModel>(product));
}
return testViewModel;
});

Mapper.AddMap<User, UserViewModel>(src =>
{
var userViewModel = new UserViewModel();
userViewModel.InjectFrom(src);
userViewModel.BelongTo = Mapper.Map<Role, RoleViewModel>(src.Role);
return userViewModel;
});

Mapper.AddMap<Author, AuthorViewModel>(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<Article, ArticleViewModel>(src.Articles.ElementAt(i));
}
authorViewModel.OwnedArticles = articles;
return authorViewModel;
});
}
}
}
24 changes: 23 additions & 1 deletion PerformanceTest/PerformanceTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,40 @@
<Reference Include="AutoMapper.Net4">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="Mapster, Version=1.14.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Mapster.1.14.0.0\lib\net45\Mapster.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Omu.ValueInjecter, Version=3.0.1.0, Culture=neutral, PublicKeyToken=c7694541b0ac80e4, processorArchitecture=MSIL">
<HintPath>..\packages\ValueInjecter.3.0.1.1\lib\net45\Omu.ValueInjecter.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="OoMapper, Version=0.2.0.33, Culture=neutral, PublicKeyToken=889bb259bb1214bf, processorArchitecture=MSIL">
<HintPath>..\packages\OoMapper.0.2.0.33\lib\net4\OoMapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="TinyMapper, Version=1.0.3.19, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\TinyMapper.1.0.18\lib\net45\TinyMapper.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Enums\Types.cs" />
<Compile Include="Generators\DataGenerator.cs" />
<Compile Include="Mapping\ExpressMappingMapping.cs" />
<Compile Include="Mapping\MapsterMapperMappings.cs" />
<Compile Include="Mapping\NativeMapping.cs" />
<Compile Include="Mapping\AutoMapperMapping.cs" />
<Compile Include="Mapping\OoMapperMappings.cs" />
<Compile Include="Mapping\TinyMapperMappings.cs" />
<Compile Include="Mapping\ValueInjectorMappings.cs" />
<Compile Include="Models\Article.cs" />
<Compile Include="Models\Author.cs" />
<Compile Include="Models\Item.cs" />
Expand All @@ -67,10 +87,12 @@
<Compile Include="Models\User.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tests\AdvancedTest.cs" />
<Compile Include="Tests\BaseTest.cs" />
<Compile Include="Tests\BaseTestResult.cs" />
<Compile Include="Tests\ComplexTest.cs" />
<Compile Include="Tests\Itest.cs" />
<Compile Include="Tests\NewsViewModel.cs" />
<Compile Include="ViewModels\NewsViewModel.cs" />
<Compile Include="Tests\SimpleStructTest.cs" />
<Compile Include="Tests\SimpleTest.cs" />
<Compile Include="Tests\SimpleWithAssociationTest.cs" />
Expand Down
Loading

0 comments on commit ba13f08

Please sign in to comment.