(转)A General Fast Method Invoker

本文介绍了一种使用动态方法调用来优化性能的技术,通过代码生成避免了反射带来的延迟,实现大约50倍的性能提升,并讨论了与传统方法调用的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(http://www.cnblogs.com/kidon/archive/2006/09/06/495936.aspx)

Introduction

Sometimes, I run across the need to dynamically invoke the method of an object, where the actual method might not be known until run-time. Usually, Reflecting is nice, but frequently doing it can be too slow. This article describes an alternative method for dynamic method invocation.

Background

When I read the article Fast Dynamic Property Accessors, I was thinking about my project, it has a lots of reflecting methods in circle. But it's methods not properties. But the DynamicMethod reminded me, maybe I could use Emit to generate a DynamicMethod to bind a special method before it can be invoked. I hope it will improve performance.

Using the Code

First, I reflected out the method which will be invoked:

MethodInfo methodInfo  =   typeof (Person).GetMethod( " Say " );

 Then, I get the MethodInvoker to invoke:

FastInvokeHandler fastInvoker  =  GetMethodInvoker(methodInfo);
fastInvoker(
new  Person(),  new   object []{ " hello " });

 Instead of using reflection method, invoke in the past:

methodInfo.Invoke( new  Person(),  new   object []{ " hello " });

Implementation

First, I need to define a delegate to adapt the dynamic method:

public   delegate   object  FastInvokeHandler( object  target, 
                                   
object [] paramters);

 It looks the same as the class MethodInfo's Invoke method. Yes, that means I can write the same code to use it like in the past.

This code generates the DynamicMethod:

public   static  FastInvokeHandler GetMethodInvoker(MethodInfo methodInfo)
{
DynamicMethod dynamicMethod 
=   new  DynamicMethod( string .Empty, 
                      
typeof ( object ),  new  Type[] {  typeof ( object ), 
                      
typeof ( object []) }, 
                      methodInfo.DeclaringType.Module);
    ILGenerator il 
=  dynamicMethod.GetILGenerator();
    ParameterInfo[] ps 
=  methodInfo.GetParameters();
     Type[] paramTypes 
=   new  Type[ps.Length];
     
for  ( int  i  =   0 ; i  <  paramTypes.Length; i ++ )
     {
         paramTypes[i] 
=  ps[i].ParameterType;
     }
     LocalBuilder[] locals 
=   new  LocalBuilder[paramTypes.Length];
     
for  ( int  i  =   0 ; i  <  paramTypes.Length; i ++ )
    {
         locals[i] 
=  il.DeclareLocal(paramTypes[i]);
     }
    
for  ( int  i  =   0 ; i  <  paramTypes.Length; i ++ )
    {
        il.Emit(OpCodes.Ldarg_1);
        EmitFastInt(il, i);
        il.Emit(OpCodes.Ldelem_Ref);
        EmitCastToReference(il, paramTypes[i]);
        il.Emit(OpCodes.Stloc, locals[i]);
    }
     il.Emit(OpCodes.Ldarg_0);
     
for  ( int  i  =   0 ; i  <  paramTypes.Length; i ++ )
     {
         il.Emit(OpCodes.Ldloc, locals[i]);
     }
     il.EmitCall(OpCodes.Call, methodInfo, 
null );
    
if  (methodInfo.ReturnType  ==   typeof ( void ))
        il.Emit(OpCodes.Ldnull);
     
else
         EmitBoxIfNeeded(il, methodInfo.ReturnType);
     il.Emit(OpCodes.Ret);
    FastInvokeHandler invoder 
=  
      (FastInvokeHandler)dynamicMethod.CreateDelegate(
       
typeof (FastInvokeHandler));
    
return  invoder;
}

Conclusion

Well, I think this is a general way that can be used instead of most of the reflection methods to get about 50 times performance improvement. Any suggestions for improvements are welcome.

Extra advantage (reminded by MaxGuernsey): If an exception occurs in your code, FastInovker would throw the original one, but the Method.Invoke would throw a TargetInvocationException.

 程序下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值