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

            上篇介绍了 Class 创建性能大比拼(反射,泛型反射,泛型创建,缓存Emit,非缓存Emit), 在这里做一个总结(执行10万次)

    • 直接创建Class对象最快 5ms
    • 缓存Emit 6ms (不包含Emit时间)
    • 泛型反射147ms
    • 泛型创建159ms(其实是编译器的语法糖,内部仍然调用泛型反射)
    • 反射340ms
    • 非缓存Emit 12786ms

         经过上面的对比应该很清楚了Class创建原则:

       直接创建->用缓存Emit->泛型反射->泛型创建->反射(反射大约比直接调用慢68倍左右),避免非缓存Emit

         这篇就来一个Struct创建性能大比拼。因为Struct和Class一个是值类型一个是引用类型,一个是分配在栈上一个是分配在堆上,用在Class上创建原则未必都和在Struct上的创建原则一致。咱们仍然以代码来说话。

        被测试的Struct:

    struct TestEntity { }

       1. 手工创建

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

      2. 反射创建

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

      3. 泛型反射创建

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

      4. 泛型直接创建

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

    static T Create<T>() where T : new()
    {
    return new T();
    }
    }

      5. 缓存Emit创建:因为结构体没有缺省构造函数,不能用IL 进行emit,这里用ExpressionTree进行Emit

     /// <summary>
            /// 得到缺省构造函数委托
            /// </summary>
            /// <param name="type"></param>
            /// <returns></returns>
            public static DefaultConstructorHandler GetDefaultCreator(this Type type)
            {
                if(type == Types.String)
                {
                    DefaultConstructorHandler s = ()=>null;
                    return s;
                }
    
                var ctorExpression = Expression.Lambda<DefaultConstructorHandler>(Expression.Convert(Expression.New(type), typeof(object)));
                var ctor = ctorExpression.Compile();
    
                DefaultConstructorHandler handler = () =>
                {
                    try
                    {
                        return ctor();
                    }
                    catch (TargetInvocationException ex)
                    {
                        throw ex.InnerException.Handle();
                    }
                    catch (Exception ex)
                    {
                        throw ex.Handle();
                    }
                };
    
                return handler;
            }
    

    基于上面Emit代码进行创建的Struct,代码如下:

    [TestInfo(Category = "Struct.Constructor", Name = "Emit")]
            class EmitInvokeMode : IRunable
            {
                //结构体没有缺省构造函数
                static readonly DefaultConstructorHandler Ctor = typeof(TestEntity).GetDefaultCreator();
    
                public void Run()
                {
                    Ctor();
                }
            }
    

    测试函数:

    for (int i = 0; i < 3; i++)
    {
    foreach (var item in Mappers)
    CodeTimer.Time(item.Metadata.Category
    + "->" + item.Metadata.Name, 100000, () => item.Value.Run());
    }

    输出结果如下:

    ------ Test started: Assembly: NLite.Test.dll ------
    
    Struct.Constructor->Direct
    	Time Elapsed:	4ms
    	CPU Cycles:	156,250
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Reflect
    	Time Elapsed:	330ms
    	CPU Cycles:	2,968,750
    	Gen 0: 		1
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->GenericReflect
    	Time Elapsed:	26ms
    	CPU Cycles:	156,250
    	Gen 0: 		1
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Generic Create
    	Time Elapsed:	3ms
    	CPU Cycles:	156,250
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Emit
    	Time Elapsed:	7ms
    	CPU Cycles:	0
    	Gen 0: 		1
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Direct
    	Time Elapsed:	1ms
    	CPU Cycles:	0
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Reflect
    	Time Elapsed:	329ms
    	CPU Cycles:	3,281,250
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->GenericReflect
    	Time Elapsed:	22ms
    	CPU Cycles:	312,500
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Generic Create
    	Time Elapsed:	4ms
    	CPU Cycles:	156,250
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Emit
    	Time Elapsed:	3ms
    	CPU Cycles:	156,250
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Direct
    	Time Elapsed:	1ms
    	CPU Cycles:	0
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Reflect
    	Time Elapsed:	339ms
    	CPU Cycles:	3,437,500
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->GenericReflect
    	Time Elapsed:	22ms
    	CPU Cycles:	312,500
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Generic Create
    	Time Elapsed:	2ms
    	CPU Cycles:	0
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    Struct.Constructor->Emit
    	Time Elapsed:	3ms
    	CPU Cycles:	0
    	Gen 0: 		0
    	Gen 1: 		0
    	Gen 2: 		0
    
    
    1 passed, 0 failed, 0 skipped, took 2.53 seconds (NUnit 2.5.5).
    

      从测试结果可以看出一个非常离奇的问题,泛型创建超过Emit超过泛型反射,这在Class的创建测试中,Emit超过泛型反射,泛型反射超过泛型创建。


  • 相关阅读:
    机器学习(十七)— SVD奇异值分解
    机器学习(十五)— Apriori算法、FP Growth算法
    机器学习(十四)— kMeans算法
    深度学习—反卷积的理解
    【ECMAScript5】ECMAScript5中有关数组的常用方法
    【window】window10永久关闭更新
    【js】使用javascript 实现静态网页分页效果
    【vue】钩子函数生命周期
    【vue】vue中ref用法
    【vue-waring】element UI 由版本1.4.12 升级到element-ui@2.0.10
  • 原文地址:https://www.cnblogs.com/netcasewqs/p/2020659.html
Copyright © 2011-2022 走看看