一个比 AutoMapper 更快的模型映射的组件 Mapster


下面是官方的性能测试 Demo,感性的也可以去 Github 上下载。

贴出代码目的是如果后期直接从自己的博客中在线看。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using AutoMapper;
using Benchmark.Classes;
using Mapster;
using FastExpressionCompiler;
using System.Linq.Expressions;

namespace Benchmark
{
    class Program
    {
        static double sAM;
        static double sMP;
        static double sMF;
        static double sEM;

        static Func<LambdaExpression, Delegate> defaultCompiler = TypeAdapterConfig.GlobalSettings.Compiler;

        static void Main(string[] args)
        {
            try
            {
                Mapper.Initialize(cfg =>
                {
                    cfg.CreateMap<Foo, Foo>();
                    cfg.CreateMap<Address, Address>();
                    cfg.CreateMap<Address, AddressDTO>();
                    cfg.CreateMap<Customer, CustomerDTO>();
                });
                TestSimpleTypes();
                TestComplexTypes();

                Console.WriteLine();
                Console.WriteLine($"======================================================================================");
                Console.WriteLine($"| Tests                | Time (ms) | Slower than Mapster | Slower than Mapster + FEC |");
                Console.WriteLine($"======================================================================================");
                Console.WriteLine($"| Mapster v3.1.8       | {  sMP,9} | { sMP / sMP,18:N2}X | {       sMP / sMF,24:N2}X |");
                Console.WriteLine($"| Mapster v3.1.8 + FEC | {  sMF,9} | { sMF / sMP,18:N2}X | {       sMF / sMF,24:N2}X |");
                Console.WriteLine($"| Automapper v7.0.1    | {  sAM,9} | { sAM / sMP,18:N2}X | {       sAM / sMF,24:N2}X |");
                Console.WriteLine($"| ExpressMapper v1.9.1 | {  sEM,9} | { sEM / sMP,18:N2}X | {       sEM / sMF,24:N2}X |");
                Console.WriteLine($"======================================================================================");
                Console.WriteLine();
            }

            finally
            {
                Console.WriteLine("Finish");
                Console.ReadLine();
            }
        }

        static void TestSimpleTypes()
        {
            Console.WriteLine("Test 1 : Simple Types");
            Console.WriteLine("Competitors : Mapster, ExpressMapper, AutoMapper");

            var foo = GetFoo();

            TestSimple(foo, 1000);

            TestSimple(foo, 10000);

            TestSimple(foo, 100000);

            TestSimple(foo, 1000000);

            //Console.WriteLine();
            //Console.WriteLine("Automapper to Mapster ratio: " + (AutomapperTime / MapsterTime).ToString("###.00") + " X slower");
            //Console.WriteLine("ExpressMapper to Mapster ratio: " + (ExpressMapperTime / MapsterTime).ToString("###.00") + " X slower");
            //Console.WriteLine();

        }

        static void TestComplexTypes()
        {
            Console.WriteLine();
            Console.WriteLine();

            Console.WriteLine("Test 2 : Complex Types");
            Console.WriteLine("Competitors : Mapster, ExpressMapper, AutoMapper");

            var customer = GetCustomer();


            //TypeAdapterConfig.GlobalSettings.DestinationTransforms.Upsert<Guid>(x => x);

            //ObjectMapperManager.DefaultInstance.GetMapper<Customer, CustomerDTO>().Map(customer);

            Test(customer, 1000);

            Test(customer, 10000);

            Test(customer, 100000);

            Test(customer, 1000000);

            Test(customer, 10000000);

            //Console.WriteLine();
            //Console.WriteLine("Automapper to Mapster ratio: " + (AutomapperTime/MapsterTime).ToString("###.00") + " X slower");
            //Console.WriteLine("ExpressMapper to Mapster ratio: " + (ExpressMapperTime/MapsterTime).ToString("###.00") + " X slower");
            //Console.WriteLine();
        }

        static void Test(Customer item, int iterations)
        {
            Console.WriteLine();

            Console.WriteLine("Iterations : {0}", iterations);

            //TestCustomerNative(item, iterations);

            TypeAdapterConfig.GlobalSettings.Compiler = defaultCompiler;    //switch compiler
            TypeAdapterConfig.GlobalSettings.Compile(typeof(Customer), typeof(CustomerDTO));    //recompile
            item.Adapt<Customer, CustomerDTO>();    //exercise
            TestMapsterAdapter<Customer, CustomerDTO>(item, iterations, ref sMP);

            TypeAdapterConfig.GlobalSettings.Compiler = exp => exp.CompileFast();    //switch compiler
            TypeAdapterConfig.GlobalSettings.Compile(typeof(Customer), typeof(CustomerDTO));    //recompile
            item.Adapt<Customer, CustomerDTO>();    //exercise
            TestMapsterAdapter<Customer, CustomerDTO>(item, iterations, ref sMF);

            ExpressMapper.Mapper.Map<Customer, CustomerDTO>(item);  //exercise
            TestExpressMapper<Customer, CustomerDTO>(item, iterations, ref sEM);

            Mapper.Map<Customer, CustomerDTO>(item);    //exercise
            TestAutoMapper<Customer, CustomerDTO>(item, iterations, ref sAM);
        }

        static void TestSimple(Foo item, int iterations)
        {



            Console.WriteLine();

            Console.WriteLine("Iterations : {0}", iterations);

            TypeAdapterConfig.GlobalSettings.Compiler = defaultCompiler;    //switch compiler
            TypeAdapterConfig.GlobalSettings.Compile(typeof(Foo), typeof(Foo));    //recompile
            item.Adapt<Foo, Foo>(); //exercise
            TestMapsterAdapter<Foo, Foo>(item, iterations, ref sMP);

            TypeAdapterConfig.GlobalSettings.Compiler = exp => exp.CompileFast();    //switch compiler
            TypeAdapterConfig.GlobalSettings.Compile(typeof(Foo), typeof(Foo));    //recompile
            item.Adapt<Foo, Foo>(); //exercise
            TestMapsterAdapter<Foo, Foo>(item, iterations, ref sMF);

            //TestValueInjecter<Foo, Foo>(item, iterations);

            ExpressMapper.Mapper.Map<Foo, Foo>(item);   //exercise
            TestExpressMapper<Foo, Foo>(item, iterations, ref sEM);

            Mapper.Map<Foo, Foo>(item);     //exercise
            TestAutoMapper<Foo, Foo>(item, iterations, ref sAM);
        }


        static void TestCustomerNative(Customer item, int iterations)
        {
            Console.WriteLine("Handwritten Mapper:\t" + Loop<Customer>(item, get =>
            {
                var dto = new CustomerDTO();

                dto.Id = get.Id;
                dto.Name = get.Name;
                dto.AddressCity = get.Address.City;

                dto.Address = new Address() { Id = get.Address.Id, Street = get.Address.Street, Country = get.Address.Country, City = get.Address.City };

                dto.HomeAddress = new AddressDTO() { Id = get.HomeAddress.Id, Country = get.HomeAddress.Country, City = get.HomeAddress.City };

                dto.Addresses = new AddressDTO[get.Addresses.Length];
                for (int i = 0; i < get.Addresses.Length; i++)
                {
                    dto.Addresses[i] = new AddressDTO() { Id = get.Addresses[i].Id, Country = get.Addresses[i].Country, City = get.Addresses[i].City };
                }

                dto.WorkAddresses = new List<AddressDTO>();
                foreach (var workAddress in get.WorkAddresses)
                {
                    dto.WorkAddresses.Add(new AddressDTO() { Id = workAddress.Id, Country = workAddress.Country, City = workAddress.City });
                }

            }, iterations));
        }


        static void TestMapsterAdapter<TSrc, TDest>(TSrc item, int iterations, ref double counter)
            where TSrc : class
            where TDest : class, new()
        {
            var time = Loop(item, get => get.Adapt<TSrc, TDest>(), iterations);
            Console.WriteLine("Mapster:\t\t" + time);
            counter += time;
        }

        static void TestExpressMapper<TSrc, TDest>(TSrc item, int iterations, ref double counter)
            where TSrc : class
            where TDest : class, new()
        {
            var time = Loop(item, get => ExpressMapper.Mapper.Map<TSrc, TDest>(get), iterations);
            Console.WriteLine("ExpressMapper:\t\t" + time);
            counter += time;
        }

        static void TestAutoMapper<TSrc, TDest>(TSrc item, int iterations, ref double counter)
            where TSrc : class
            where TDest : class, new()
        {
            //if (iterations > 50000)
            //    Console.WriteLine("AutoMapper still working please wait...");

            var time = Loop(item, get => Mapper.Map<TSrc, TDest>(get), iterations);
            Console.WriteLine("AutoMapper:\t\t" + time);
            counter += time;
        }

        static long Loop<T>(T item, Action<T> action, int iterations = 1000000)
        {
            return Time(item, a =>
            {
                for (int i = 0; i < iterations; i++)
                {
                    action(a);
                }
            });
        }

        static long Time<T>(T item, Action<T> action)
        {
            var sw = new Stopwatch();
            sw.Start();
            action(item);
            sw.Stop();
            return sw.ElapsedMilliseconds;
        }


        #region Data

        static Customer GetCustomer()
        {
            Customer c = new Customer()
            {
                Address = new Address() { City = "istanbul", Country = "turkey", Id = 1, Street = "istiklal cad." },
                HomeAddress = new Address() { City = "istanbul", Country = "turkey", Id = 2, Street = "istiklal cad." },
                Id = 1,
                Name = "Eduardo Najera",
                Credit = 234.7m,
                WorkAddresses = new List<Address>()
                {
                    new Address() {City = "istanbul", Country = "turkey", Id = 5, Street = "istiklal cad."},
                    new Address() {City = "izmir", Country = "turkey", Id = 6, Street = "konak"}
                },
                Addresses = new List<Address>()
                {
                    new Address() {City = "istanbul", Country = "turkey", Id = 3, Street = "istiklal cad."},
                    new Address() {City = "izmir", Country = "turkey", Id = 4, Street = "konak"}
                }.ToArray()
            };

            return c;
        }

        static Foo GetFoo()
        {
            var o = new Foo
            {
                Name = "foo",
                Int32 = 12,
                Int64 = 123123,
                NullInt = 16,
                DateTime = DateTime.Now,
                Doublen = 2312112,
                Foo1 = new Foo { Name = "foo one" },
                Foos = new List<Foo>
                {
                    new Foo {Name = "j1", Int64 = 123, NullInt = 321},
                    new Foo {Name = "j2", Int32 = 12345, NullInt = 54321},
                    new Foo {Name = "j3", Int32 = 12345, NullInt = 54321},
                },
                FooArr = new[]
                {
                    new Foo {Name = "a1"},
                    new Foo {Name = "a2"},
                    new Foo {Name = "a3"},
                },
                IntArr = new[] { 1, 2, 3, 4, 5 },
                Ints = new[] { 7, 8, 9 },
            };

            return o;
        }

        #endregion

    }
}

 

 

谢谢浏览!


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM