1

我试图通过创建一个 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
4

0 回答 0