- 直接创建Class对象最快 5ms
- 缓存Emit 6ms (不包含Emit时间)
- 泛型反射147ms
- 泛型创建159ms(其实是编译器的语法糖,内部仍然调用泛型反射)
- 反射340ms
- 非缓存Emit 12786ms
直接创建->用缓存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
4. 泛型直接创建
[TestInfo(Category = "Struct.Constructor", Name = "Generic Create")] class GenericCreateInvokeMode : IRunable { public void Run() { Create
5. 缓存Emit创建:因为结构体没有缺省构造函数,不能用IL 进行emit,这里用ExpressionTree进行Emit
///
///
基于上面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超过泛型反射,泛型反射超过泛型创建。
最新评论