zoukankan      html  css  js  c++  java
  • Class 创建性能大比拼(反射,泛型反射,泛型创建,缓存Emit,非缓存Emit)

      一说到反射,很多人都想到了性能,更有甚者直接说“慎用反射,遗患无穷”,“用反射,感觉怎么像是退步啊~”,看到这种言论,直接把反射妖魔化了,如果这种言论长此以往,势必会对很多对反射初学者造成负面影响。反射是一把双刃剑,看你怎样使用了,下面我就用代码说话。

    class TestEntity { }
    

      1. 手工创建TestEntity 

    [TestInfo(Category = "Class.Constructor", Name = "Direct")]
    class DirectInvokeMode:IRunable
    {
    public void Run()
    {
    new TestEntity();
    }
    }

         2. 反射创建TestEntity 

    [TestInfo(Category = "Class.Constructor", Name = "Reflect")]
    class ReflectInvokeMode : IRunable
    {
    public void Run()
    {
    Activator.CreateInstance(
    typeof(TestEntity));
    }
    }

      3. 泛型反射创建TestEntity

    [TestInfo(Category = "Class.Constructor", Name = "GenericReflect")]
    class GenericReflectInvokeMode : IRunable
    {
    public void Run()
    {
    Activator.CreateInstance
    <TestEntity>();
    }
    }

      4. Generic 直接创建

    [TestInfo(Category = "Class.Constructor", Name = "Generic Create")]
    class GenericCreateInvokeMode : IRunable
    {
    public void Run()
    {
    Create
    <TestEntity>();
    }

    static T Create<T>() where T : new()
    {
    return new T();
    }
    }
    5. Emit创建
    [TestInfo(Category = "Class.Constructor", Name = "Emit")]
    class EmitInvokeMode : IRunable
    {
    static readonly ConstructorHandler Ctor = typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator();

    public void Run()
    {
    Ctor();
    }
    }

      6. 不缓存Emit的创建

    [TestInfo(Category = "Class.Constructor", Name = "NoCacheEmit")]
    class NoCacheEmitInvokeMode : IRunable
    {
    public void Run()
    {
    typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator()();
    }
    }

      测试程序:(执行10万次创建Class对象)

    foreach (var item in Mappers)
    CodeTimer.Time(item.Metadata.Category
    + "->" + item.Metadata.Name, 100000, () => item.Value.Run());

    输出结果:

    ------ Test started: Assembly: NLite.Test.dll ------


    Class.Constructor
    ->Direct
    Time Elapsed: 5ms
    CPU Cycles:
    0
    Gen
    0: 1
    Gen
    1: 0
    Gen
    2: 0

    Class.Constructor
    ->Reflect
    Time Elapsed: 320ms
    CPU Cycles:
    2,968,750
    Gen
    0: 1
    Gen
    1: 0
    Gen
    2: 0

    Class.Constructor
    ->GenericReflect
    Time Elapsed: 147ms
    CPU Cycles:
    1,250,000
    Gen
    0: 1
    Gen
    1: 0
    Gen
    2: 0

    Class.Constructor
    ->Generic Create
    Time Elapsed: 159ms
    CPU Cycles:
    1,406,250
    Gen
    0: 1
    Gen
    1: 0
    Gen
    2: 0

    Class.Constructor
    ->Emit
    Time Elapsed: 6ms
    CPU Cycles:
    0
    Gen
    0: 2
    Gen
    1: 0
    Gen
    2: 0

    Class.Constructor
    ->NoCacheEmit
    Time Elapsed:
    12,786ms
    CPU Cycles:
    119,218,750
    Gen
    0: 162
    Gen
    1: 81
    Gen
    2: 0

    1 passed, 0 failed, 0 skipped, took 67.77 seconds (NUnit 2.5.5).

      性能比较结果应该是一目了然了!

          附上源代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NUnit.Framework;
    using System.Reflection;
    using NLite.Reflection;
    
    namespace NLite.Test.Reflection
    {
        [Contract]
        public interface IRunable
        {
            void Run();
        }
    
        //测试器元数据
        public interface ITestInfo
        {
            //目录
            string Category { get; }
            //名称
            string Name { get; }
        }
    
        //映射器元数据注解
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
        [MetadataAttributeAttribute]
        public class TestInfoAttribute : ComponentAttribute
        {
            public string Category { get; set; }
            public string Name { get; set; }
        }
    
    
        [TestFixture]
        public class SpecBase
        {
            public SpecBase()
            {
            }
    
            [SetUp]
            public void SetUp()
            {
                Given();
                When();
            }
    
            public virtual void Given() { }
            public virtual void When()
            {
            }
    
            [Test]
            public void Test()
            {
                
            }
        }
    
        public abstract class PerformanceSpecBase : SpecBase
        {
            [InjectMany]
            protected Lazy<IRunable, ITestInfo>[] Mappers;
    
            protected abstract void RegisterComponents();
    
            public virtual int Times
            {
                get { return 100000; }
            }
    
            public override void Given()
            {
                RegisterComponents();
                ServiceRegistry.Compose(this);
            }
    
    
            public override void When()
            {
                for (int i = 0; i < 3; i++)
                {
                    foreach (var item in Mappers)
                        CodeTimer.Time(item.Metadata.Category + "->" + item.Metadata.Name, Times, () => item.Value.Run());
                }
            }
        }
    
        public class InvokeConstructorPerformanceSpec : PerformanceSpecBase
        {
            class TestEntity { }
    
            protected override void RegisterComponents()
            {
                ServiceRegistry
                    .Register<DirectInvokeMode>()
                    .Register<ReflectInvokeMode>()
                    .Register<GenericReflectInvokeMode>()
                    .Register <GenericCreateInvokeMode>()
                    .Register<EmitInvokeMode>()
                    .Register < NoCacheEmitInvokeMode>()
                    .Register < GenericReflectInvokeMode2>()
                    ;
            }
            [TestInfo(Category = "Class.Constructor", Name = "Direct")]
            class DirectInvokeMode:IRunable
            {
                public void Run()
                {
                    new TestEntity();
                }
            }
    
            [TestInfo(Category = "Class.Constructor", Name = "Reflect")]
            class ReflectInvokeMode : IRunable
            {
                public void Run()
                {
                    Activator.CreateInstance(typeof(TestEntity));
                }
            }
    
            [TestInfo(Category = "Class.Constructor", Name = "GenericReflect")]
            class GenericReflectInvokeMode : IRunable
            {
                public void Run()
                {
                    Activator.CreateInstance<TestEntity>();
                }
            }
    
            [TestInfo(Category = "Class.Constructor", Name = "Reflect->Reflect")]
            class GenericReflectInvokeMode2 : IRunable
            {
                static readonly MethodInfo CreateMethod = typeof(Activator)
                    .GetMethod("CreateInstance", Type.EmptyTypes)
                    .MakeGenericMethod(typeof(TestEntity));
    
                public void Run()
                {
                    CreateMethod.Invoke(null,null);
                }
    
    
            }
    
            
    
            [TestInfo(Category = "Class.Constructor", Name = "Generic Create")]
            class GenericCreateInvokeMode : IRunable
            {
                public void Run()
                {
                    Create<TestEntity>();
                }
    
                static T Create<T>() where T : new()
                {
                    return new T();
                }
            }
    
            [TestInfo(Category = "Class.Constructor", Name = "Emit")]
            class EmitInvokeMode : IRunable
            {
                static readonly ConstructorHandler Ctor = typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator();
    
                public void Run()
                {
                    Ctor();
                }
            }
    
    
            [TestInfo(Category = "Class.Constructor", Name = "NoCacheEmit")]
            class NoCacheEmitInvokeMode : IRunable
            {
                public void Run()
                {
                    typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator()();
                }
            }
    
    
        }
    
       
    }
    

          最后给大家一个思考题:Struct 创建性能大比拼的结果是怎样的?(注意Struct是值类型,Class是引用类型,值类型是分配在栈上的,引用类型是分配在堆上的)

  • 相关阅读:
    Python异常捕捉try except else finally有return时执行顺序探究
    为什么在Python的线程内调用sys.exit()时不退出?
    Hadoop集群上用户使用crontab时候失败
    记一次--------spark 读 mysql 报错no suitable driver
    通用权限sql设计
    union all 对结果进行分类展示
    雷达图
    常用语句
    oracle中计算两个日期的相差天数、月数、年数、小时数、分钟数、秒数等
    icell设计器发送邮件不成功
  • 原文地址:https://www.cnblogs.com/netcasewqs/p/2019999.html
Copyright © 2011-2022 走看看