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超过泛型反射,泛型反射超过泛型创建。


posted @ 2011-04-19 11:18  风云  阅读(2780)  评论(14编辑  收藏  举报