直接调用vs反射调用实例教程

  很多人都说使用反射会有性能问题,那到底会比直接调用慢多少呢,下面就来测试一下。

直接调用vs反射调用

下面就来写个demo来验证下直接调用和反射调用的性能差异,代码如下:

 1 namespace ConsoleApplication7 2 { 3     class Program 4     { 5         static void Main(string[] args) 6         { 7             //比较直接调用和反射调用的性能差异 8             //7ms vs 365ms 9             int times = 1000000;10             var program = new Program();11             CodeTimerHelper.Initialize();12 13             CodeTimerHelper.Time("直接调用", times, () =>14             {15                 program.Call();16             });17 18             var t = typeof(Program);19             var obj = Activator.CreateInstance(t);20             CodeTimerHelper.Time("反射调用", times, () =>21             {22                 t.InvokeMember("Call", BindingFlags.InvokeMethod, null, obj, null);23             });24 25             Console.ReadKey();26         }27 28         /// 29         /// 测试方法30         /// 31         public void Call()32         {33         }34 35     }36 }

登录后复制

 

测试结果:

直接调用vs反射调用实例教程

从100万次调用结果来看,确实就像很多人所说的,两者在性能上具有数量级的差距。 

 

为什么反射有性能损失

既然反射性能有损失,那具体损失在哪里呢?

1,反射是基于程序集和元数据的,在使用反射的时候,会搜索元数据,而元数据是基于字符串的,并且无法预编译,所以这一系列的操作对性能有影响。

2,大量的装箱拆箱也对性能有影响。由于我们对目标类型是未知的,而且向方法传递的参数通常是object类型的,所以会有大量的装箱和拆箱。

 

反射性能优化方案

我们已经知道使用反射有性能问题,但是有些场景下又不得不使用反射技术,所以要想办法优化反射性能。

这里就引用老赵公开的System.Linq.Expressions.Expression表达式树的类,与直接调用进行对比,代码如下:

1 //3,基于表达式树2 var methodInfo = t.GetMethod("Call");3 var executor = new DynamicMethodExecutor(methodInfo);4 CodeTimerHelper.Time("Dynamic executor", times, () =>5 {6     executor.Execute(obj, null);7 });

登录后复制

 

测试结果:

直接调用vs反射调用实例教程

哇,同样的100万次调用,使用DynamicMethodExecutor调用跟直接调用的性能相差无几。

附DynamicMethodExecutor的封装代码:

 1 ///  2 ///  3 ///  4 public class DynamicMethodExecutor 5 { 6     private Func m_execute; 7  8     public DynamicMethodExecutor(MethodInfo methodInfo) 9     {10         this.m_execute = this.GetExecuteDelegate(methodInfo);11     }12 13     public object Execute(object instance, object[] parameters)14     {15         return this.m_execute(instance, parameters);16     }17 18     private Func GetExecuteDelegate(MethodInfo methodInfo)19     {20         // parameters to execute21         ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");22         ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");23 24         // build parameter list25         List parameterExpressions = new List();26         ParameterInfo[] paramInfos = methodInfo.GetParameters();27         for (int i = 0; i < paramInfos.Length; i++)28         {29             // (Ti)parameters[i]30             BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));31             UnaryExpression valueCast = Expression.Convert(valueObj, paramInfos[i].ParameterType);32             parameterExpressions.Add(valueCast);33         }34 35         // non-instance for static method, or ((TInstance)instance)36         Expression instanceCast = methodInfo.IsStatic ? null : Expression.Convert(instanceParameter, methodInfo.ReflectedType);37 38         // static invoke or ((TInstance)instance).Method39         MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);40 41         // ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...)42         if (methodCall.Type == typeof(void))43         {44             Expression<Action> lambda = Expression.Lambda<Action>(methodCall, instanceParameter, parametersParameter);45             Action execute = lambda.Compile();46             return (instance, parameters) =>47             {48                 execute(instance, parameters);49                 return null;50             };51         }52         else53         {54             UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));55             Expression<Func> lambda = Expression.Lambda<Func>(castMethodCall, instanceParameter, parametersParameter);56             return lambda.Compile();57         }58     }

登录后复制

 

 除了使用linq的表达式树生成Delegate的方法外,还有比如,CodeDom生成代码并动态编译,或者使用Emit来直接编写IL的方法来提高反射的性能,但是相对来说,上面这个方法是最简单的。

至此,整个反射的总结就完成了!

参考文章

方法的直接调用,反射调用与……Lambda表达式调用

C#基础知识梳理系列十五:反射

二、什么是反射、反射可以做些什么

以上就是直接调用vs反射调用实例教程的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2494174.html

(0)
上一篇 2025年3月5日 01:47:00
下一篇 2025年2月24日 09:53:15

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • C#开发中遇到的问题分享

    1、构造函数不能带返回值类型,因为构造函数返回就是对象本身。 2、将字符串转换成日期类型,用DateTime.Parese()或DateTime. ParseExact ()函数。 3、if(!Page.IsPostback){} 使用该函…

    编程技术 2025年3月5日
    200
  • ASP.NET一些经典的问题详解

       1、asp.net能在那些系统中运行?    目前,asp.net还只能奔跑在微软的windows 2000、windows xp和windows 2003的系统中,并且需要微软internet information server(…

    编程技术 2025年3月5日
    200
  • .net中关于异步性能测试的示例代码

    很久没有写博客了,今年做的产品公司这两天刚刚开了发布会,稍微清闲下来,想想我们做的产品还有没有性能优化空间,于是想到了.net的异步可以优化性能,但到底能够提升多大的比例呢?恰好有一个朋友正在做各种语言的异步性能测试(有关异步和同步的问题,…

    2025年3月5日 编程技术
    200
  • 案例分享c++ map的使用和 查找性能测试

    最近在为推荐服务作性能调优,这个服务的主要逻辑是用离线计算的模型数据给请求中的每个广告打分,再返回这些广告的排序结果,这里面打分的过程其实就用请求中的数据拼成各种key,去查一个大的 map,这种计算非常多,成为了主要的性能瓶颈,代码比较老…

    编程技术 2025年3月5日
    200
  • 为什么我的Go程序无法正确使用连接池库?

    go语言中使用连接池库是一个很常见的操作,它可以提高程序的性能和效率。然而,有时候你的程序可能会出现连接池无法正确使用的问题,导致程序无法正常工作。这篇文章将解释可能的原因和解决方案。 首先,我们需要了解连接池的基本原理。连接池是通过预先创…

    编程技术 2025年3月4日
    200
  • Golang开发:优化数据库连接池的性能与效率

    Golang开发:优化数据库连接池的性能与效率 引言:在Golang开发中,数据库连接池的性能和效率对于应用程序的稳定性和性能至关重要。过多的数据库连接资源的浪费或者不足的资源分配都会导致应用的性能下降甚至崩溃。因此,优化数据库连接池的性能…

    2025年3月4日
    200
  • 利用Go语言连接数据库:提高应用程序性能与效率

    使用Go语言连接数据库:提升应用程序的性能和效率 随着应用程序的发展和用户量的增加,对数据的存储和处理变得越来越重要。为了提高应用程序的性能和效率,合理地连接和操作数据库是至关重要的一环。 Go语言作为一种快速、可靠、并发性强的开发语言,具…

    2025年3月4日
    200
  • Go语言与其他编程语言的性能对比及优劣势

    标题:Go语言与其他编程语言的性能对比及优劣势 随着计算机技术的不断发展,编程语言的选择越来越关键,其中性能是一个重要的考量因素。本文将以Go语言为例,与其他常见的编程语言进行性能对比,并分析各自的优劣势。 一、Go语言概述 Go语言是由G…

    2025年3月4日
    200
  • golang框架性能对比:框架对网络请求的处理效率

    基准测试表明 fasthttp 的网络请求处理效率最佳。fasthttp 以每秒 120,000 个请求的吞吐量超越了 gin、gorm 和 echo 等框架。fasthttp 的高性能使其非常适合处理高并发网络请求场景,例如分布式微服务和…

    2025年3月4日
    200
  • golang框架中数据库访问的性能优化

    优化 go 框架中数据库访问性能的方法:使用 orm(对象关系映射)框架:简化数据库访问,消除编写冗长 sql 查询和处理结果集的需要。缓存查询结果:减少对数据库的调用次数,提高性能。使用预编译语句:提高性能,避免 sql 查询的解析和编译…

    2025年3月4日
    200

发表回复

登录后才能评论