MethodInfo.Invoke性能问题

我正在读取文件和从文件写入数据。 文件中的数据可以是浮点数,双精度数,整数等。直到运行时才知道该类型。 我将存储在文件中的数据类型称为Tin。 数据被读入或写入Tout类型的数组。 直到运行时才知道这种类型。

代码序列是这样的。 在Open方法中,Tin和Tout是已知的,我们可以为已知数据类型创建读写方法。

Open(...) { MethodInfo ReadMethod = typeof(...)GetMethod("ReadGeneric").MakeGenericMethod(new Type[] {typeof(Tin), typeof(Tout)})); } 

读写循环重复数百万次,并依赖于reflection来调用适当的方法,如下所示。

 Read loop { var values = (Tout[])ReadMethod.Invoke(this,new object[]{index}); process ... } 

当使用性能分析器检查此代码时,如果只花时间调用运行时读写方法,我会发现c collosal amount。

我该如何加快速度呢?

是的,这是因为reflectionAPI比直接方法调用慢了数千倍。 然而,有一些有趣的技术可以解决这个问题。 查看Jon Skeet关于使用委托缓存reflection的文章。

存在静态设置成本,但是一旦完成,重复调用委托的时间等同于虚方法调用。

还有一些预先打包的框架可以实现同样的function。

这对你来说都有所作为,几乎和直接通话一样快。

 using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; public class FastMethodInfo { private delegate object ReturnValueDelegate(object instance, object[] arguments); private delegate void VoidDelegate(object instance, object[] arguments); public FastMethodInfo(MethodInfo methodInfo) { var instanceExpression = Expression.Parameter(typeof(object), "instance"); var argumentsExpression = Expression.Parameter(typeof(object[]), "arguments"); var argumentExpressions = new List(); var parameterInfos = methodInfo.GetParameters(); for (var i = 0; i < parameterInfos.Length; ++i) { var parameterInfo = parameterInfos[i]; argumentExpressions.Add(Expression.Convert(Expression.ArrayIndex(argumentsExpression, Expression.Constant(i)), parameterInfo.ParameterType)); } var callExpression = Expression.Call(!methodInfo.IsStatic ? Expression.Convert(instanceExpression, methodInfo.ReflectedType) : null, methodInfo, argumentExpressions); if (callExpression.Type == typeof(void)) { var voidDelegate = Expression.Lambda(callExpression, instanceExpression, argumentsExpression).Compile(); Delegate = (instance, arguments) => { voidDelegate(instance, arguments); return null; }; } else Delegate = Expression.Lambda(Expression.Convert(callExpression, typeof(object)), instanceExpression, argumentsExpression).Compile(); } private ReturnValueDelegate Delegate { get; } public object Invoke(object instance, params object[] arguments) { return Delegate(instance, arguments); } } 

通过配置文件找到符合您期望的解决方案:

.Net Framework提供了大量调用动态方法的方法。 然而,它们在性能方面表现不同,并且它们不易同样易于使用。

CreateDelegate可能就是你要找的东西

在.Net Framework的最新版本中,CreateDelegate在MethodInfo调用时击败因子50:

 // The following should be done once since this does some reflection var method = typeof (...).GetMethod("ReadGeneric"); // Here we create a Func that targets the instance of type which has the // ReadGeneric method var func = (Func)_method.CreateDelegate(typeof(Func), target); // Func will be 50x faster than MethodInfo.Invoke // use func as a standard Func like // var tout = func(index); 

查看我的这篇文章,看看不同方法调用的基准