惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
G
Google Developers Blog
B
Blog
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 叶小钗
The Cloudflare Blog
The Hacker News
The Hacker News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
雷峰网
雷峰网
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
Last Week in AI
Last Week in AI
T
Threat Research - Cisco Blogs
A
About on SuperTechFans
量子位
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
H
Help Net Security
Help Net Security
Help Net Security
P
Palo Alto Networks Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Troy Hunt's Blog
W
WeLiveSecurity
V
Vulnerabilities – Threatpost
T
The Exploit Database - CXSecurity.com
Know Your Adversary
Know Your Adversary
Apple Machine Learning Research
Apple Machine Learning Research
Scott Helme
Scott Helme
N
News | PayPal Newsroom
AWS News Blog
AWS News Blog
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
MongoDB | Blog
MongoDB | Blog
B
Blog RSS Feed
腾讯CDC
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
TaoSecurity Blog
TaoSecurity Blog
GbyAI
GbyAI
Y
Y Combinator Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Docker

博客园 - 我有我奥妙

【自动注入】.NET8/.NETCore 依赖注入:自动注入项目中所有接口和自定义类 【排名】处理同分数的排名 【Quartz】.Net8使用定时任务 【模型验证】未被异常捕获到 【Ant Design Vue】相关 【根节点】C#找树形数据的根节点Id 【C#】枚举值 【ECharts】图表自定义显示标题 【消息队列】介绍 【Nginx】Windows部署Vue 设计模式(一)-介绍 【.NetCore】创建本机的静态文件服务器 NLog(一)-使用示例 【nssm】windows上netcore注册为服务 【字符串排序】C#和前端js排序问题 【长路经】C#读取文件抛出FileNotFoundException异常 【RestSharp】常用的几个请求方式 【笔记软件】Obsidian的使用 【浏览器扩展】编写Firefox和Chrome的扩展程序
【BenchmarkDotNet】测试多方式的对象映射
我有我奥妙 · 2026-01-31 · via 博客园 - 我有我奥妙

前言

此为粗略结果,未做完善的缓存和预热操作,仅供参考

创建项目

(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