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

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是引用类型,值类型是分配在栈上的,引用类型是分配在堆上的)

转载于:https://www.cnblogs.com/netcasewqs/archive/2011/04/18/2019999.html

Class 创建性能大比拼(反射,泛型反射,泛型创建,缓存Emit,非缓存Emit)相关推荐

  1. 【Java反射】反射机制性能问题、反射操作泛型

    反射性能问题 相比普通的方法调用来说,反射会降低程序的运行效率.但是反射可以增加开发的效率,可以让整个项目更快开发,所以仍然被我们大量使用. 禁止安全检查,可以提高反射的运行速度: 使用普通方法调用. ...

  2. 【JavaLearn】(19)反射、Class类、使用反射创建对象-操作属性-执行方法、泛型与反射、反射案例

    目录 1. 反射 1.1 反射引入 1.2 反射的入口-Class类 2. 认识 Class 类 3. 使用反射创建对象 4. 使用反射操作属性 5. 使用反射执行方法 6. 使用反射操作泛型 6.2 ...

  3. 【JavaLearn】#(19)反射、Class类、使用反射创建对象-操作属性-执行方法、泛型与反射、反射案例

    1. 反射 1.1 反射引入 编译时,知道类或对象的具体信息,此时直接对类和对象进行操作即可 编译时不知道类或对象的具体信息,只有运行时知道,需要使用反射来实现 ==> 比如驱动的类的名称放在 ...

  4. java 泛型反射_Java使用反射来获取泛型信息示例

    本文实例讲述了Java使用反射来获取泛型信息.分享给大家供大家参考,具体如下: 一 点睛 获得了Field对象后,就可以很容易地获得该Field的数据类型,即使用如下代码即可获得指定Field的类型: ...

  5. java 反射和泛型-反射来获取泛型信息

    通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public.获得Field对象后都可以使用getType()来获取其类型. Class&l ...

  6. 反射——通过反射越过泛型检查

    一.目的 通过反射来越过泛型检查 二.应用场景 向 ArrayList <Integer> 中添加一个 字符串数据 代码: public static void main(String[] ...

  7. c 与java 反射性能_谈谈Java 反射的快慢

    [相关学习推荐:java基础教程] 反射到底是好是坏 说到Java 中的反射,初学者在刚刚接触到反射的各种高级特性时,往往表示十分兴奋,甚至会在一些不需要使用反射的场景中强行使用反射来「炫技」.而经验 ...

  8. 反射创建对象_如何应用Java反射技术灵活地创建程序类的对象实例

    软件项目实训及课程设计指导--如何应用Java反射技术灵活地创建程序类的对象实例 1.如何应用属性配置文件实现对系统中的配置信息进行读写操作 Java中的属性配置文件主要可以作为软件应用系统及项目的配 ...

  9. 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 使用反射获取方法创建本应用的 dexElements | 各版本创建 dex 数组源码对比 )

    文章目录 一.不同 Android 系统创建 dex 数组源码对比 二.不同 Android 系统创建 dex 数组源码对比 三. Android 5.1 及以下系统反射方法并创建 Element[] ...

最新文章

  1. python提取图像的每一帧
  2. 【星云测试】开发者测试-采用精准测试工具对Spring Boot应用进行测试
  3. 另一个小程序 返回的支付结果如何得到_所以,你想用 $8 的价格修一个bug吗?...
  4. 微信公众号开发 [03] 结合UEditor实现图文消息群发功能
  5. 仿微博国际版首页点击显示分组列表(popupwindow悬浮阴影效果)
  6. [Leetcode][第114题][JAVA][二叉树展开为链表][递归][迭代]
  7. 惠普:存储为未来而设计
  8. rabbitmq添加自启动 centos7环境
  9. 第三方支付处理厂商软件有漏洞,日本美容零售商Acro 10万支付卡信息遭攻击
  10. sftp访问_实时数据处理探索:接收、处理、访问
  11. 华为荣耀手机指令代码大全_2020.10月《各价位华为、荣耀手机推荐》
  12. Atitit.软件兼容性原理与实践   v5 qa2.docx
  13. linux查看dubbo版本号,Dubbo 疯狂更新!
  14. java实现Word文档(doc、docx)在线查看功能(前台+后台)
  15. 2022-2027年(新版)中国LCP行业发展前景及需求规模预测报告
  16. CODESYS自动化仿真软件如何与EtherNet IP工业RID读写器|读卡器CK-RF102AN-E01联机工作
  17. 计算化学软件 Schrodinger | 资源收集
  18. 服务器default文件夹可以删除吗,C盘用户文件夹里的Default是什么文件夹,有什么用,能删除么?...
  19. [Nowcoder] [Wannafly26B] 冥土追魂 [贪心]
  20. element-ui select下拉框 设置默认值

热门文章

  1. ES5-8 闭包高级、对象、构造函数、实例化
  2. Alpine Linux详解
  3. api-gateway实践(03)新服务网关 - 网关请求拦截检查
  4. js function理解
  5. Nginx 笔记与总结(14)expires 缓存设置
  6. Android应用开发中的风格和主题(style,themes)
  7. android之多媒体篇(一)
  8. [转]Xvid参数详解
  9. 运放的主要参数详细介绍
  10. matlab simulink笔记02——延迟模块delay与单位延迟模块unit delay