HigLabo.Mapper performance test
Benchmark Results:
Benchmark Code:
using FastMapper;
using HigLabo.Core;
using Mapster;
using Nelibur.ObjectMapper;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AgileObjects;
using BenchmarkDotNet.Running;
using HigLabo.Mapper.TestNotSupported;
using System.Linq.Expressions;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.Reflection;
using System.Buffers;
namespace HigLabo.Mapper.PerformanceTest
{
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<MapperPerformanceTest>();
Console.ReadLine();
}
}
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Jobs;
namespace HigLabo.Mapper.PerformanceTest
{
public class BenchmarkConfig : ManualConfig
{
public BenchmarkConfig()
{
AddExporter(MarkdownExporter.GitHub);
AddDiagnoser(MemoryDiagnoser.Default);
//AddJob(Job.ShortRun);
}
}
[Config(typeof(BenchmarkConfig))]
public class MapperPerformanceTest
{
private AutoMapper.MapperConfiguration _AutoMapperConfiguration = null;
public static readonly Int32 ExecuteCount = 1000;
public AutoMapper.IMapper AutoMapper = null;
public Customer Customer = null;
public Address Address = null;
public TC0_Members TC0_Members = null;
[GlobalSetup]
public void Setup()
{
_AutoMapperConfiguration = new AutoMapper.MapperConfiguration(config => {
config.CreateMap<Customer, Customer>();
config.CreateMap<Customer, CustomerDTO>();
config.CreateMap<Address, AddressDTO>();
});
this.AutoMapper = _AutoMapperConfiguration.CreateMapper();
TinyMapper.Bind<Address, Address>();
TinyMapper.Bind<Address, AddressDTO>();
TinyMapper.Bind<Customer, Customer>();
TinyMapper.Bind<Customer, CustomerDTO>();
HigLabo.Core.ObjectMapper.Default.CompilerConfig.ClassPropertyCreateMode = ClassPropertyCreateMode.NewObject;
HigLabo.Core.ObjectMapper.Default.CompilerConfig.CollectionElementCreateMode = CollectionElementCreateMode.NewObject;
this.Customer = Customer.Create();
this.Address = Address.Create();
this.TC0_Members = TC0_Members.Create();
}
[Benchmark(Baseline = true)]
public void HandwriteMapper_Address()
{
var address = Address.Create();
for (int i = 0; i < ExecuteCount; i++)
{
this.MapAddress(address, new Address());
}
}
private void MapAddress(Address address, Address addressTo)
{
addressTo.Id = address.Id;
addressTo.City = address.City;
addressTo.Country = address.Country;
addressTo.AddressType = address.AddressType;
}
[Benchmark]
public void HigLaboObjectMapper_Address()
{
var mapper = ObjectMapper.Default;
var md = mapper.GetMapMethod<Address, Address>();
for (int i = 0; i < ExecuteCount; i++)
{
var r = md(mapper, this.Address, new Address());
}
}
[Benchmark]
public void Mapperly_Address()
{
var mapper = new MapperlyMapper();
for (int i = 0; i < ExecuteCount; i++)
{
var r = mapper.AddressToAddress(this.Address);
}
}
[Benchmark]
public void Mapster_Address()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.Address.Adapt(new Address());
}
}
[Benchmark]
public void AutoMapper_Address()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.AutoMapper.Map<Address>(this.Address);
}
}
[Benchmark]
public void ExpressMapper_Address()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = ExpressMapper.Mapper.Map<Address, Address>(this.Address);
}
}
[Benchmark]
public void AgileMapper_Address()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = AgileObjects.AgileMapper.Mapper.Map(this.Address).ToANew<Address>();
}
}
[Benchmark]
public void FastMapper_Address()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = FastMapper.TypeAdapter.Adapt<Address, Address>(this.Address);
}
}
[Benchmark]
public void TinyMapper_Address()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = TinyMapper.Map<Address>(this.Address);
}
}
[Benchmark]
public void HandwriteMapper_AddressDTO()
{
var address = Address.Create();
for (int i = 0; i < ExecuteCount; i++)
{
this.MapAddressDTO(address, new AddressDTO());
}
}
private void MapAddressDTO(Address address, AddressDTO addressDto)
{
addressDto.Id = address.Id;
addressDto.City = address.City;
addressDto.Country = address.Country;
addressDto.AddressType = address.AddressType;
}
[Benchmark]
public void HigLaboObjectMapper_AddressDTO()
{
var mapper = ObjectMapper.Default;
var md = mapper.GetMapMethod<Address, AddressDTO>();
for (int i = 0; i < ExecuteCount; i++)
{
var r = md(mapper, this.Address, new AddressDTO());
}
}
[Benchmark]
public void Mapperly_AddressDTO()
{
var mapper = new MapperlyMapper();
for (int i = 0; i < ExecuteCount; i++)
{
var r = mapper.AddressToAddressDto(this.Address);
}
}
[Benchmark]
public void Mapster_AddressDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.Address.Adapt(new AddressDTO());
}
}
[Benchmark]
public void AutoMapper_AddressDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.AutoMapper.Map<AddressDTO>(this.Address);
}
}
[Benchmark]
public void ExpressMapper_AddressDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = ExpressMapper.Mapper.Map<Address, AddressDTO>(this.Address);
}
}
[Benchmark]
public void AgileMapper_AddressDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = AgileObjects.AgileMapper.Mapper.Map(this.Address).ToANew<AddressDTO>();
}
}
[Benchmark]
public void FastMapper_AddressDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = FastMapper.TypeAdapter.Adapt<Address, AddressDTO>(this.Address);
}
}
[Benchmark]
public void TinyMapper_AddressDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var addressDto = TinyMapper.Map<AddressDTO>(this.Address);
}
}
[Benchmark]
public void HigLaboObjectMapper_Customer()
{
var mapper = ObjectMapper.Default;
var md = mapper.GetMapMethod<Customer, Customer>();
for (int i = 0; i < ExecuteCount; i++)
{
var r = md(mapper, this.Customer, new Customer());
}
}
[Benchmark]
public void Mapperly_Customer()
{
var mapper = new MapperlyMapper();
for (int i = 0; i < ExecuteCount; i++)
{
var r = mapper.CustomerToCustomer(this.Customer);
}
}
[Benchmark]
public void Mapster_Customer()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.Customer.Adapt(new Customer());
}
}
[Benchmark]
public void AutoMapper_Customer()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.AutoMapper.Map<Customer>(this.Customer);
}
}
[Benchmark]
public void ExpressMapper_Customer()
{
var customer = Customer.Create();
var count = ExecuteCount;
for (int i = 0; i < count; i++)
{
var customerDto = ExpressMapper.Mapper.Map<Customer, Customer>(customer);
}
}
[Benchmark]
public void AgileMapper_Customer()
{
var customer = Customer.Create();
var count = ExecuteCount;
for (int i = 0; i < count; i++)
{
var customerDto = AgileObjects.AgileMapper.Mapper.Map<Customer>(customer).ToANew<Customer>();
}
}
[Benchmark]
public void FastMapper_Customer()
{
var customer = Customer.Create();
var count = ExecuteCount;
for (int i = 0; i < count; i++)
{
var customerDto = FastMapper.TypeAdapter.Adapt<Customer, Customer>(customer);
}
}
[Benchmark]
public void TinyMapper_Customer()
{
var customer = Customer.Create();
var count = ExecuteCount;
for (int i = 0; i < count; i++)
{
var customerDto = TinyMapper.Map<Customer>(customer);
}
}
[Benchmark]
public void HandwriteMapper_Customer_CustomerDTO()
{
var customer = Customer.Create();
for (int i = 0; i < ExecuteCount; i++)
{
this.MapCustomer(customer, new CustomerDTO());
}
}
private void MapCustomer(Customer customer, CustomerDTO customerDto)
{
customerDto.Id = customer.Id;
customerDto.Name = customer.Name;
customerDto.Address = new Address();
customerDto.Address.Id = customer.Address.Id;
customerDto.Address.Street = customer.Address.Street;
customerDto.Address.City = customer.Address.City;
customerDto.Address.Country = customer.Address.Country;
customerDto.AddressList = new AddressDTO[customer.AddressList.Length];
for (int aIndex = 0; aIndex < customer.AddressList.Length; aIndex++)
{
customerDto.AddressList[aIndex] = new AddressDTO();
customerDto.AddressList[aIndex].Id = customer.AddressList[aIndex].Id;
customerDto.AddressList[aIndex].City = customer.AddressList[aIndex].City;
customerDto.AddressList[aIndex].Country = customer.AddressList[aIndex].Country;
}
customerDto.HomeAddress = new AddressDTO();
customerDto.HomeAddress.Id = customerDto.HomeAddress.Id;
customerDto.HomeAddress.City = customerDto.HomeAddress.City;
customerDto.HomeAddress.Country = customerDto.HomeAddress.Country;
customer.WorkAddressList = new List<Address>();
foreach (var item in customer.WorkAddressList)
{
customerDto.WorkAddressList.Add(new AddressDTO()
{
Id = item.Id,
City = item.City,
Country = item.Country,
});
}
foreach (var item in customer.WorkAddressList)
{
customerDto.WorkAddressList.Add(new AddressDTO()
{
Id = item.Id,
City = item.City,
Country = item.Country,
});
}
}
[Benchmark]
public void HigLaboObjectMapper_Customer_CustomerDTO()
{
var mapper = ObjectMapper.Default;
var md = mapper.GetMapMethod<Customer, CustomerDTO>();
for (int i = 0; i < ExecuteCount; i++)
{
var r = md(mapper, this.Customer, new CustomerDTO());
}
}
[Benchmark]
public void Mapperly_Customer_CustomerDTO()
{
var mapper = new MapperlyMapper();
for (int i = 0; i < ExecuteCount; i++)
{
var r = mapper.CustomerToCustomerDto(this.Customer);
}
}
[Benchmark]
public void Mapster_Customer_CustomerDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.Customer.Adapt(new CustomerDTO());
}
}
[Benchmark]
public void AutoMapper_Customer_CustomerDTO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.AutoMapper.Map<CustomerDTO>(this.Customer);
}
}
[Benchmark]
public void HigLaboObjectMapper_TC0_Members_To_Tc0_I0_MembersO()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = HigLabo.Core.ObjectMapper.Default.Map(this.TC0_Members, new TC0_I0_Members());
}
}
[Benchmark]
public void Mapster_TC0_Members_To_Tc0_I0_Members()
{
for (int i = 0; i < ExecuteCount; i++)
{
var r = this.TC0_Members.Adapt(new TC0_I0_Members());
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HigLabo.Mapper.PerformanceTest
{
public class Person
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Emails { get; set; }
public Person Parent { get; set; }
public static Person Create()
{
var p = new Person();
p.Id = Guid.NewGuid();
p.FirstName = "Joe";
p.LastName = "Mickelson";
p.Emails = "joe@email.com";
return p;
}
}
public enum AddressType
{
House,
Building,
}
public class Address
{
public static readonly Random Random = new Random();
public int Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
public AddressType AddressType { get; set; }
public static Address Create()
{
var a = new Address();
a.Id = GetRandomNumber();
a.Street = "Street" + GetRandomNumber();
a.City = "City" + GetRandomNumber();
a.Country = "USA " + GetRandomNumber();
a.AddressType = AddressType.House;
return a;
}
private static Int32 GetRandomNumber()
{
return Random.Next(100);
}
}
public class AddressDTO
{
public int Id { get; set; }
public string City { get; set; }
public string Country { get; set; }
public AddressType AddressType { get; set; } = AddressType.House;
public GpsPosition Gps { get; set; }
}
public struct GpsPosition
{
public double Latitude { get; private set; }
public double Longitude { get; private set; }
public GpsPosition(double latitude, double longitude)
{
this.Latitude = latitude;
this.Longitude = longitude;
}
}
public class Customer
{
public static readonly Random Random = new Random();
public Int32? Id { get; set; }
public String Name { get; set; }
public Address Address { get; set; }
public Address HomeAddress { get; set; }
public Address[] AddressList { get; set; }
public IEnumerable<Address> WorkAddressList { get; set; }
public static Customer Create()
{
Customer customer = new Customer()
{
Id = 1,
Name = "Timucin Kivanc " + GetRandomNumber(),
Address = new Address()
{
City = "Istanbul " + GetRandomNumber(),
Country = "Turkey " + GetRandomNumber(),
Id = 1,
Street = "Istiklal cad. " + GetRandomNumber(),
}
};
customer.HomeAddress = new Address()
{
City = "Istanbul " + GetRandomNumber(),
Country = "Turkey " + GetRandomNumber(),
Id = 2,
Street = "Istiklal cad. " + GetRandomNumber(),
};
customer.WorkAddressList = new Address[]
{
new Address()
{
City = "Istanbul " + GetRandomNumber(),
Country = "Turkey " + GetRandomNumber(),
Id = 5,
Street = "Istiklal cad. " + GetRandomNumber(),
},
new Address()
{
City = "Izmir " + GetRandomNumber(),
Country = "Turkey " + GetRandomNumber(),
Id = 6,
Street = "Konak " + GetRandomNumber(),
}
};
customer.AddressList = new Address[]
{
new Address()
{
City = "Istanbul " + GetRandomNumber(),
Country = "Turkey " + GetRandomNumber(),
Id = 3,
Street = "Istiklal cad. " + GetRandomNumber(),
},
new Address()
{
City = "Izmir " + GetRandomNumber(),
Country = "Turkey " + GetRandomNumber(),
Id = 4,
Street = "Konak " + GetRandomNumber(),
}
};
return customer;
}
private static Int32 GetRandomNumber()
{
return Random.Next(100);
}
}
public class CustomerDTO
{
public Int32? Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public AddressDTO HomeAddress { get; set; }
public AddressDTO[] AddressList { get; set; }
public List<AddressDTO> WorkAddressList { get; set; }
public String AddressCity { get; set; }
}
public class Organization
{
public string Name { get; set; }
public Organization Parent { get; set; }
public List<Organization> ChildOrganizations { get; private set; }
public Organization()
{
this.ChildOrganizations = new List<PerformanceTest.Organization>();
}
}
public class SiteSummaryData
{
public CollectionWithPropety Data { get; private set; }
public SiteSummaryData()
{
this.Data = new CollectionWithPropety();
}
public static SiteSummaryData Create()
{
var data = new SiteSummaryData();
data.Data = new CollectionWithPropety();
data.Data.Name = "Tag Data 2016/11";
data.Data.Year = 2016;
data.Data.Month = 11;
data.Data.Tags = new[] { "C#", "Ruby", "AWS" };
data.Data.TagList.AddRange(new[] { "C#", "Ruby", "AWS" });
for (int i = 0; i < 20; i++)
{
data.Data.AccessData.Add(new CollectionWithPropety.AccessInfo()
{
Date = DateTime.Now.AddDays(-20 + i),
AccessCount = i * 100
});
}
return data;
}
}
public class CollectionWithPropety
{
public class AccessInfo
{
public DateTime Date { get; set; }
public Int32 AccessCount { get; set; }
}
public String Name { get; set; }
public Int32 Year { get; set; }
public Int32 Month { get; set; }
public String[] Tags { get; set; }
public List<String> TagList { get; private set; }
public List<AccessInfo> AccessData { get; private set; }
public CollectionWithPropety()
{
this.Tags = new String[0];
this.TagList = new List<string>();
this.AccessData = new List<AccessInfo>();
}
}
public class Vector2
{
public Int16 Value { get; set; }
}
public class Vector3
{
public Int32 Value { get; set; }
}
public class TreeNode
{
public List<TreeNode> Nodes { get; set; }
public TreeNode()
{
}
}
public class NotSupportedSource_TinyMapper
{
public Single? Credit { get; set; }
public String EmployeeCount { get; set; } = "1234";
}
public class NotSupportedTarget_TinyMapper
{
public Decimal? Credit { get; set; }
public Int32 EmployeeCount { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace HigLabo.Mapper.PerformanceTest
{
public enum TUndefinedABCEnum
{
Undefined,
A,
B,
C
}
public enum TABCEnum
{
A,
B,
C
}
public class TC0_Members : IComparable<TC0_Members>
{
public int Id { get; set; }
public bool BooleanMember { get; set; }
public char CharMember { get; set; }
public sbyte SByteMember { get; set; }
public byte ByteMember { get; set; }
public short Int16SMember { get; set; }
public ushort UInt16Member { get; set; }
public int Int32Member { get; set; }
public uint UInt32Member { get; set; }
public long Int64Member { get; set; }
public ulong UInt64Member { get; set; }
public float SingleMember { get; set; }
public double DoubleMember { get; set; }
public decimal DecimalMember { get; set; }
public string StringMember { get; set; }
public DateTime DateTimeMember { get; set; }
public DateTimeOffset DateTimeOffsetMember { get; set; }
public TimeSpan TimeSpanMember { get; set; }
public Guid GuidMember { get; set; }
public TUndefinedABCEnum UndefinedEnumMember { get; set; }
public TABCEnum EnumMember { get; set; }
public int CompareTo(TC0_Members other)
{
return Id.CompareTo(other.Id);
}
public static TC0_Members Create()
{
var s = new TC0_Members();
s.Id = 1;
s.BooleanMember = true;
s.CharMember = 'a';
s.SByteMember = 3;
s.ByteMember = 8;
s.Int16SMember = -16;
s.UInt16Member = 16;
s.Int32Member = -32;
s.UInt32Member = 32;
s.Int64Member = -64;
s.UInt64Member = 64;
s.SingleMember = 123f;
s.DoubleMember = 256d;
s.DecimalMember = 512m;
s.StringMember = "str";
s.DateTimeMember = new DateTime(2020, 10, 17);
s.DateTimeOffsetMember = new DateTimeOffset(s.DateTimeMember, TimeSpan.FromHours(9));
s.TimeSpanMember = TimeSpan.FromHours(4);
s.GuidMember = Guid.Parse("6987f244-0ab2-4998-b6cf-39dc2a014ee0");
s.UndefinedEnumMember = TUndefinedABCEnum.A;
s.EnumMember = TABCEnum.B;
return s;
}
}
public class TC0_I0_Members : IComparable<TC0_I0_Members>
{
public bool BooleanMember { get; set; }
public char CharMember { get; set; }
public sbyte SByteMember { get; set; }
public byte ByteMember { get; set; }
public short Int16SMember { get; set; }
public ushort UInt16Member { get; set; }
public int Int32Member { get; set; }
public uint UInt32Member { get; set; }
public long Int64Member { get; set; }
public ulong UInt64Member { get; set; }
public float SingleMember { get; set; }
public double DoubleMember { get; set; }
public decimal DecimalMember { get; set; }
public string StringMember { get; set; }
public int CompareTo(TC0_I0_Members other)
{
return Int32Member.CompareTo(other.Int32Member);
}
}
public class TC0_I1_Members : IComparable<TC0_I1_Members>
{
public bool BooleanMember { get; set; }
public char CharMember { get; set; }
public sbyte SByteMember { get; set; }
public byte ByteMember { get; set; }
public short Int16SMember { get; set; }
public ushort UInt16Member { get; set; }
public int Int32Member { get; set; }
public uint UInt32Member { get; set; }
public long Int64Member { get; set; }
public ulong UInt64Member { get; set; }
public float SingleMember { get; set; }
public double DoubleMember { get; set; }
public decimal DecimalMember { get; set; }
public string StringMember { get; set; }
public DateTime DateTimeMember { get; set; }
public DateTimeOffset DateTimeOffsetMember { get; set; }
public TimeSpan TimeSpanMember { get; set; }
public Guid GuidMember { get; set; }
public TUndefinedABCEnum UndefinedEnumMember { get; set; }
public TABCEnum EnumMember { get; set; }
public int CompareTo(TC0_I1_Members other)
{
return Int32Member.CompareTo(other.Int32Member);
}
}
public class TC0_I2_Nullable_Members : IComparable<TC0_I2_Nullable_Members>
{
public bool? BooleanMember { get; set; }
public char? CharMember { get; set; }
public sbyte? SByteMember { get; set; }
public byte? ByteMember { get; set; }
public short? Int16SMember { get; set; }
public ushort? UInt16Member { get; set; }
public int? Int32Member { get; set; }
public uint? UInt32Member { get; set; }
public long? Int64Member { get; set; }
public ulong? UInt64Member { get; set; }
public float? SingleMember { get; set; }
public double? DoubleMember { get; set; }
public decimal? DecimalMember { get; set; }
public string StringMember { get; set; }
public DateTime? DateTimeMember { get; set; }
public DateTimeOffset? DateTimeOffsetMember { get; set; }
public TimeSpan? TimeSpanMember { get; set; }
public Guid? GuidMember { get; set; }
public TUndefinedABCEnum? UndefinedEnumMember { get; set; }
public TABCEnum? EnumMember { get; set; }
public int CompareTo(TC0_I2_Nullable_Members other)
{
return (Int32Member != null ? Int32Member.Value : 0)
.CompareTo(other.Int32Member != null ? other.Int32Member.Value : 0);
}
}
public struct TS0_Members : IComparable<TS0_Members>
{
public int Id { get; set; }
public bool BooleanMember { get; set; }
public char CharMember { get; set; }
public sbyte SByteMember { get; set; }
public byte ByteMember { get; set; }
public short Int16SMember { get; set; }
public ushort UInt16Member { get; set; }
public int Int32Member { get; set; }
public uint UInt32Member { get; set; }
public long Int64Member { get; set; }
public ulong UInt64Member { get; set; }
public float SingleMember { get; set; }
public double DoubleMember { get; set; }
public decimal DecimalMember { get; set; }
public string StringMember { get; set; }
public DateTime DateTimeMember { get; set; }
public DateTimeOffset DateTimeOffsetMember { get; set; }
public TimeSpan TimeSpanMember { get; set; }
public Guid GuidMember { get; set; }
public TUndefinedABCEnum UndefinedEnumMember { get; set; }
public TABCEnum EnumMember { get; set; }
public int CompareTo(TS0_Members other)
{
return Id.CompareTo(other.Id);
}
}
public struct TS0_I0_Members : IComparable<TS0_I0_Members>
{
public bool BooleanMember { get; set; }
public char CharMember { get; set; }
public sbyte SByteMember { get; set; }
public byte ByteMember { get; set; }
public short Int16SMember { get; set; }
public ushort UInt16Member { get; set; }
public int Int32Member { get; set; }
public uint UInt32Member { get; set; }
public long Int64Member { get; set; }
public ulong UInt64Member { get; set; }
public float SingleMember { get; set; }
public double DoubleMember { get; set; }
public decimal DecimalMember { get; set; }
public string StringMember { get; set; }
public int CompareTo(TS0_I0_Members other)
{
return Int32Member.CompareTo(other.Int32Member);
}
}
public struct TS0_I1_Members : IComparable<TS0_I1_Members>
{
public bool BooleanMember { get; set; }
public char CharMember { get; set; }
public sbyte SByteMember { get; set; }
public byte ByteMember { get; set; }
public short Int16SMember { get; set; }
public ushort UInt16Member { get; set; }
public int Int32Member { get; set; }
public uint UInt32Member { get; set; }
public long Int64Member { get; set; }
public ulong UInt64Member { get; set; }
public float SingleMember { get; set; }
public double DoubleMember { get; set; }
public decimal DecimalMember { get; set; }
public string StringMember { get; set; }
public DateTime DateTimeMember { get; set; }
public DateTimeOffset DateTimeOffsetMember { get; set; }
public TimeSpan TimeSpanMember { get; set; }
public Guid GuidMember { get; set; }
public TUndefinedABCEnum UndefinedEnumMember { get; set; }
public TABCEnum EnumMember { get; set; }
public int CompareTo(TS0_I1_Members other)
{
return Int32Member.CompareTo(other.Int32Member);
}
}
public struct TS0_I2_Nullable_Members : IComparable<TS0_I2_Nullable_Members>
{
public bool? BooleanMember { get; set; }
public char? CharMember { get; set; }
public sbyte? SByteMember { get; set; }
public byte? ByteMember { get; set; }
public short? Int16SMember { get; set; }
public ushort? UInt16Member { get; set; }
public int? Int32Member { get; set; }
public uint? UInt32Member { get; set; }
public long? Int64Member { get; set; }
public ulong? UInt64Member { get; set; }
public float? SingleMember { get; set; }
public double? DoubleMember { get; set; }
public decimal? DecimalMember { get; set; }
public string StringMember { get; set; }
public DateTime? DateTimeMember { get; set; }
public DateTimeOffset? DateTimeOffsetMember { get; set; }
public TimeSpan? TimeSpanMember { get; set; }
public Guid? GuidMember { get; set; }
public TUndefinedABCEnum? UndefinedEnumMember { get; set; }
public TABCEnum? EnumMember { get; set; }
public int CompareTo(TS0_I2_Nullable_Members other)
{
return (Int32Member != null ? Int32Member.Value : 0)
.CompareTo(other.Int32Member != null ? other.Int32Member.Value : 0);
}
}
public class TC1
{
public TC0_Members I0 { get; set; }
public TC0_Members I1 { get; set; }
public TC0_Members I2 { get; set; }
}
public class TC1_0
{
public TC0_I0_Members I0 { get; set; }
public TC0_I1_Members I1 { get; set; }
public TC0_I2_Nullable_Members I2 { get; set; }
}
public class TS1
{
public TS0_Members I0 { get; set; }
public TS0_Members I1 { get; set; }
public TS0_Members I2 { get; set; }
}
public class TS1_0
{
public TS0_I0_Members I0 { get; set; }
public TS0_I1_Members I1 { get; set; }
public TS0_I2_Nullable_Members I2 { get; set; }
}
}
Powered by SharpLab
// .NET 8 Lowered C# Code unavailable due to errors:
error CS1529: A using clause must precede all other elements defined in the namespace except extern alias declarations
error CS1513: } expected
error CS0246: The type or namespace name 'FastMapper' could not be found (are you missing a using directive or an assembly reference?)
error CS0234: The type or namespace name 'Core' does not exist in the namespace 'HigLabo' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'Mapster' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'Nelibur' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'AgileObjects' could not be found (are you missing a using directive or an assembly reference?)
error CS0234: The type or namespace name 'TestNotSupported' does not exist in the namespace 'HigLabo.Mapper' (are you missing an assembly reference?)
error CS0234: The type or namespace name 'DataAnnotations' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'AutoMapper' could not be found (are you missing a using directive or an assembly reference?)
error CS0103: The name 'MarkdownExporter' does not exist in the current context
error CS0103: The name 'MemoryDiagnoser' does not exist in the current context
error CS0103: The name 'TinyMapper' does not exist in the current context
error CS0234: The type or namespace name 'Core' does not exist in the namespace 'HigLabo.Mapper.PerformanceTest.HigLabo' (are you missing an assembly reference?)
error CS0103: The name 'ClassPropertyCreateMode' does not exist in the current context
error CS0103: The name 'CollectionElementCreateMode' does not exist in the current context
error CS0103: The name 'ObjectMapper' does not exist in the current context
error CS0246: The type or namespace name 'MapperlyMapper' could not be found (are you missing a using directive or an assembly reference?)
error CS1061: 'Address' does not contain a definition for 'Adapt' and no accessible extension method 'Adapt' accepting a first argument of type 'Address' could be found (are you missing a using directive or an assembly reference?)
error CS0103: The name 'ExpressMapper' does not exist in the current context
error CS0103: The name 'AgileObjects' does not exist in the current context
error CS0103: The name 'FastMapper' does not exist in the current context
error CS1061: 'Customer' does not contain a definition for 'Adapt' and no accessible extension method 'Adapt' accepting a first argument of type 'Customer' could be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'MapperPerformanceTest' could not be found (are you missing a using directive or an assembly reference?)
error CS1061: 'TC0_Members' does not contain a definition for 'Adapt' and no accessible extension method 'Adapt' accepting a first argument of type 'TC0_Members' could be found (are you missing a using directive or an assembly reference?)
Powered by SharpLab
// .NET 8 IL Code unavailable due to errors:
error CS1529: A using clause must precede all other elements defined in the namespace except extern alias declarations
error CS1513: } expected
error CS0246: The type or namespace name 'FastMapper' could not be found (are you missing a using directive or an assembly reference?)
error CS0234: The type or namespace name 'Core' does not exist in the namespace 'HigLabo' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'Mapster' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'Nelibur' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'AgileObjects' could not be found (are you missing a using directive or an assembly reference?)
error CS0234: The type or namespace name 'TestNotSupported' does not exist in the namespace 'HigLabo.Mapper' (are you missing an assembly reference?)
error CS0234: The type or namespace name 'DataAnnotations' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'AutoMapper' could not be found (are you missing a using directive or an assembly reference?)
error CS0103: The name 'TinyMapper' does not exist in the current context
error CS0234: The type or namespace name 'Core' does not exist in the namespace 'HigLabo.Mapper.PerformanceTest.HigLabo' (are you missing an assembly reference?)
error CS0103: The name 'ClassPropertyCreateMode' does not exist in the current context
error CS0103: The name 'CollectionElementCreateMode' does not exist in the current context
error CS0103: The name 'ObjectMapper' does not exist in the current context
error CS0246: The type or namespace name 'MapperlyMapper' could not be found (are you missing a using directive or an assembly reference?)
error CS1061: 'Address' does not contain a definition for 'Adapt' and no accessible extension method 'Adapt' accepting a first argument of type 'Address' could be found (are you missing a using directive or an assembly reference?)
error CS0103: The name 'ExpressMapper' does not exist in the current context
error CS0103: The name 'AgileObjects' does not exist in the current context
error CS0103: The name 'FastMapper' does not exist in the current context
error CS1061: 'Customer' does not contain a definition for 'Adapt' and no accessible extension method 'Adapt' accepting a first argument of type 'Customer' could be found (are you missing a using directive or an assembly reference?)
error CS1061: 'TC0_Members' does not contain a definition for 'Adapt' and no accessible extension method 'Adapt' accepting a first argument of type 'TC0_Members' could be found (are you missing a using directive or an assembly reference?)
error CS0103: The name 'MarkdownExporter' does not exist in the current context
error CS0103: The name 'MemoryDiagnoser' does not exist in the current context
error CS0246: The type or namespace name 'MapperPerformanceTest' could not be found (are you missing a using directive or an assembly reference?)
Powered by SharpLab
|
Benchmark Description:
The provided benchmark code is designed to evaluate the performance of various object mapping libraries and techniques in .NET. Object mapping is a common requirement in software development, where data needs to be transferred between different object instances, possibly of different types. This benchmark aims to measure the speed and efficiency of different mapping approaches, which is crucial for applications that require high performance and scalability.
### General Setup
- **.NET Version**: Not explicitly mentioned, but the use of `BenchmarkDotNet` suggests it's likely targeting a recent .NET Core or .NET 5/6 version.
- **Configuration**: Uses `BenchmarkDotNet` for running and measuring benchmarks. A custom `BenchmarkConfig` class configures the benchmark environment, including the use of a memory diagnoser to measure memory allocations and the Markdown exporter for results presentation.
- **Libraries Tested**:
- Handwritten mappers
- `HigLabo`
- `Mapster`
- `AutoMapper`
- `ExpressMapper`
- `AgileMapper`
- `FastMapper`
- `TinyMapper`
### Benchmark Methods Rationale
1. **HandwriteMapper_Address/AddressDTO**:
- **Purpose**: Measures the performance of manually written mapping code.
- **Importance**: Serves as a baseline for comparison, showing how manual optimizations can impact performance.
- **Expected Insights**: Typically, handwritten mappings are expected to be among the fastest and least memory-intensive, as they are tailor-made without any overhead from generalization.
2. **Library-Specific Mappings (e.g., HigLaboObjectMapper_Address, Mapster_Address)**:
- **Purpose**: Each method tests the mapping performance of a specific library for the same source and target types.
- **Importance**: Allows direct comparison of library efficiency in terms of execution speed and memory usage.
- **Expected Insights**: Reveals the overhead introduced by each library's generic handling of mappings and their optimization capabilities.
3. **HigLaboObjectMapper_Customer/CustomerDTO**:
- **Purpose**: Tests more complex object graphs that include nested objects and collections.
- **Importance**: Evaluates how each library handles more complex scenarios, which are common in real-world applications.
- **Expected Insights**: Highlights the libraries' abilities to deal with complex object graphs, including any optimizations for collections or handling of nested mappings.
4. **HigLaboObjectMapper_TC0_Members_To_Tc0_I0_MembersO**:
- **Purpose**: Focuses on mapping between objects with a large number of fields, including various data types.
- **Importance**: Tests the libraries' performance and memory usage when mapping between objects with many fields, simulating data-rich domain models.
- **Expected Insights**: Provides insight into how each library scales with the complexity and size of the data structure.
### General Insights Expected
- **Performance**: The benchmarks are expected to show a range of performances, with handwritten mappings generally being the fastest due to their lack of overhead. Libraries that can closely approach this performance while offering the convenience of automatic mapping would be considered highly efficient.
- **Memory Usage**: Memory allocation is a critical factor, especially in high-throughput or resource-constrained environments. The benchmarks should highlight which libraries are more conservative in their memory usage.
- **Ease vs. Efficiency Trade-off**: There's typically a trade-off between the ease of use provided by automatic mapping libraries and the efficiency of handwritten mappings. These benchmarks help quantify that trade-off, aiding in choosing the right tool for a given scenario.
### Conclusion
These benchmarks are designed to provide a comprehensive overview of the performance characteristics of various object mapping strategies in .NET. By understanding the trade-offs involved, developers can make informed decisions about which mapping approach or library best fits their application's requirements in terms of speed, memory usage, and development effort.