我试图通过创建一个 DynamicMethod 来降低反射方法的调用时间,用它的 IL 生成器发出 IL 代码,然后使用它的 CreateDelegate 方法创建一个委托。到目前为止,即使新方法调用仍使用 (object callObject, object[] params) 作为参数,调用时间也显着减少。当返回类型不是 void 时,生成的 IL 代码中会出现问题。我对MSIL一无所知,做了很多研究,但一无所获。这是有效的代码:
private void Start()
{
var a = new A();
var method = typeof(A).GetMethod("Add");
Type[] paramsTypes = { typeof(object[]) };
Type[] allTypes = { typeof(object), typeof(object[]) };
Type returnType = typeof(void);
var dm = new DynamicMethod("Hi", returnType, allTypes);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, paramsTypes);
il.Emit(OpCodes.Ret);
var del4 = (Action<object, object[]>)dm.CreateDelegate(
typeof(Action<object, object[]>));
var time = DateTime.Now;
for (int i = 0; i < 20000000; i++)
{
//a.Add(); 132 ms
//method.Invoke(a, null);// 25 sec
del4(a, null); // 200 ms
}
var ts = DateTime.Now - time;
Debug.Log($"{ts.Seconds}:{ts.Milliseconds}");
}
public class A
{
public int a = 0;
public void Add() => a++;
}
结果时间(仅测量调用时间)与普通 MethodInfo.Invoke 相比要快得多。但是,通过以下调整,IL 生成器会抛出错误:
private void Start()
{
var a = new A();
var method = typeof(A).GetMethod("Add");
Type[] paramsTypes = { typeof(object[]) };
Type[] allTypes = { typeof(object), typeof(object[]) };
Type returnType = typeof(object);
var dm = new DynamicMethod("Hi", returnType, allTypes);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, paramsTypes);
il.Emit(OpCodes.Ret);
var del4 = (Func<object, object[], object>)dm.CreateDelegate(
typeof(Func<object, object[], object>));
var time = DateTime.Now;
for (int i = 0; i < 20000000; i++)
{
//a.Add(); 132 ms
//method.Invoke(a, null);// 25 sec
del4(a, null); // 200 ms
}
var ts = DateTime.Now - time;
Debug.Log($"{ts.Seconds}:{ts.Milliseconds}");
}
public class A
{
public int a = 0;
public int Add() => a++;
}
当预期的返回类型不是 void 时,将引发以下异常:
InvalidProgramException: Invalid IL code in (wrapper dynamic-method) object:Hi (object,object[]): IL_0006: ret
有谁知道如何解决这个问题?
编辑:在返回操作码之前添加了装箱:
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, paramsTypes);
il.Emit(OpCodes.Box);
il.Emit(OpCodes.Ret);
然后抛出以下内容:
VerificationException: Error in System.Object:(wrapper dynamic-method) object:Hi (object,object[]) Invalid instruction 8c