





















此为粗略结果,未做完善的缓存和预热操作,仅供参考
(1)项目名称
MyBenchmarks
(2)添加引用
<PackageReference Include="AutoMapper" Version="16.0.0" />
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="NLog" Version="6.0.7" />
<PackageReference Include="TinyMapper" Version="3.0.3" />
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Nelibur.ObjectMapper;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Linq.Expressions;
namespace MyBenchmarks
{
public class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<MappingBenchmarks>();
Console.ReadLine();
}
}
[MemoryDiagnoser]
public class MappingBenchmarks
{
private IServiceCollection _services = null;
private SourceDto _source = null;
private AutoMapper.IMapper _mapper = null;
private ILoggerFactory _loggerFactory = null;
private IsoDateTimeConverter _timeConverter = null;
[GlobalSetup]
public void Setup()
{
_services = new ServiceCollection();
_services.AddLogging(builder =>
{
builder.SetMinimumLevel(LogLevel.Information);
});
var serviceProvider = _services.BuildServiceProvider();
_loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
_source = new SourceDto()
{
Id = DateTime.Now.Second,
Name = DateTime.Now.Second.ToString(),
CreatedAt = DateTime.Now,
};
TinyMapper.Bind<SourceDto, DestDto>();
var config = new AutoMapper.MapperConfiguration(c => c.CreateMap<SourceDto, DestDto>(), _loggerFactory);
_mapper = config.CreateMapper();
_timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
}
[Benchmark(Baseline = true)]
public DestDto ManualBuild()
{
return new DestDto
{
Id = _source.Id,
Name = _source.Name,
CreatedAt = _source.CreatedAt,
};
}
[Benchmark]
public DestDto TinyMapperMap()
{
return TinyMapper.Map<DestDto>(_source);
}
[Benchmark]
public DestDto AutoMapperMap()
{
return _mapper.Map<DestDto>(_source);
}
[Benchmark]
public DestDto MapsterMap()
{
return _source.Adapt<DestDto>();
}
[Benchmark]
public DestDto JsonMap()
{
var json = JsonConvert.SerializeObject(_source, _timeConverter);
return JsonConvert.DeserializeObject<DestDto>(json);
}
[Benchmark]
public DestDto CopyPropertiesMap()
{
var target = new DestDto();
{
var sourceType = _source.GetType();
var targetType = target.GetType();
foreach (var prop in sourceType.GetProperties())
{
var targetProp = targetType.GetProperty(prop.Name);
if (targetProp != null && targetProp.PropertyType == prop.PropertyType)
{
targetProp.SetValue(target, prop.GetValue(_source));
}
}
}
return target;
}
[Benchmark]
public DestDto ExpressionGenericMapperMap()
{
return ExpressionGenericMapper<SourceDto, DestDto>.Trans(_source);
}
}
public class ExpressionGenericMapper<TInput, TResult>
{
private static Func<TInput, TResult> _FUNC;
static ExpressionGenericMapper()
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TInput), "p");
List<MemberBinding> memberBindingList = new List<MemberBinding>();
foreach (var item in typeof(TResult).GetProperties())
{
MemberExpression property = Expression.Property(parameterExpression, typeof(TInput).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingList.Add(memberBinding);
}
foreach (var item in typeof(TResult).GetFields())
{
MemberExpression field = Expression.Field(parameterExpression, typeof(TInput).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, field);
memberBindingList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TResult)), memberBindingList.ToArray());
Expression<Func<TInput, TResult>> lambda = Expression.Lambda<Func<TInput, TResult>>(memberInitExpression, new ParameterExpression[] {
parameterExpression
});
_FUNC = lambda.Compile();
}
public static TResult Trans(TInput t)
{
return _FUNC(t);
}
}
public class SourceDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
}
public class DestDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
}
}
需 Release 模式下运行
以 PowerShell 为例
进入项目目录
运行
dotnet run -c Release --project MyBenchmarks.csproj
(1)机器信息
BenchmarkDotNet v0.15.8, Windows 10 (10.0.19045.5737/22H2/2022Update)
13th Gen Intel Core i5-13400F 2.50GHz, 1 CPU, 16 logical and 10 physical cores
.NET SDK 10.0.100
[Host] : .NET 8.0.22 (8.0.22, 8.0.2225.52707), X64 RyuJIT x86-64-v3
DefaultJob : .NET 8.0.22 (8.0.22, 8.0.2225.52707), X64 RyuJIT x86-64-v3
(2)表格
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| ManualBuild | 4.032 ns | 0.0402 ns | 0.0336 ns | 1.00 | 0.01 | 0.0038 | 40 B | 1.00 |
| TinyMapperMap | 13.273 ns | 0.1201 ns | 0.1003 ns | 3.29 | 0.04 | 0.0038 | 40 B | 1.00 |
| AutoMapperMap | 41.105 ns | 0.2242 ns | 0.2097 ns | 10.19 | 0.10 | 0.0038 | 40 B | 1.00 |
| MapsterMap | 10.444 ns | 0.0665 ns | 0.0590 ns | 2.59 | 0.03 | 0.0038 | 40 B | 1.00 |
| JsonMap | 1,160.986 ns | 13.3922 ns | 12.5271 ns | 287.94 | 3.81 | 0.4787 | 5016 B | 125.40 |
| CopyPropertiesMap | 117.775 ns | 1.3882 ns | 1.1592 ns | 29.21 | 0.36 | 0.0129 | 136 B | 3.40 |
| ExpressionGenericMapperMap | 4.499 ns | 0.0832 ns | 0.0778 ns | 1.12 | 0.02 | 0.0038 | 40 B | 1.00 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。