【问题标题】:Use reflection stub to initialize a delegate field lazily使用反射存根懒惰地初始化委托字段
【发布时间】:2009-10-21 10:08:43
【问题描述】:

问题:

  • 一个 .Net 2.0 类,由代码生成器生成数千个委托字段

    1. 不同的签名
    2. 委托可能会也可能不会返回值
    3. 没有泛型
  • 这些委托可以在运行时快速初始化

    1. 初始化委托很简单,但昂贵
    2. 现在初始化整个批次的成本约为 300 毫秒 - 可以接受,但并不完美
    3. 用户可能会使用不到 10% 的这些委托 - 如果我们只能延迟加载这些委托,它会快得多! (不要为不使用的东西付费)

问题:

是否可以使用反射来懒惰地初始化委托字段?在伪代码中:

class Delegates
{
    int FooDelegate(IntPtr p1, float* p2);
    public static FooDelegate Foo;
    // Several thousand more    
    ...

    static Delegate LoadDelegate(string name, Type signature)
    {
        // complex and expensive p/invokes
    }

    static void SetupStubs()
    {
        // Create loader stubs (using reflection because
        // JIT times are prohibitive when done inline)
        foreach (FieldInfo f in typeof(Delegates)
            .GetFields(BindingFlags.Static | BindingFlags.NonPublic))
        {
            // We need to generate a compatible delegate, which:
            // (a) calls LoadDelegate("Foo", typeof(FooDelegate)), and
            // (b) assigns its result to the Foo field (replacing the stub),
            // (c) executes Foo(p1, p2) and returns the result, where 
            // p1 and p2 are the original parameters specified by the user.
            Delegate stub = ...;
            f.SetValue(null, stub);
        }
    }
}

我有一种感觉 可以创建一个执行 (a)、(b) 和 (c) 的存根,但我还没有设法预测 如何 em>。

理想情况下,代码应该运行 .Net 2.0 和 Mono 2.0,并且应该使用 System.Reflection.Emit。不过,我也对使用 .Net 3.5 或 DynamicMethod 的解决方案感兴趣。

有什么想法吗? :)

【问题讨论】:

    标签: c# .net lazy-loading delegates stub


    【解决方案1】:

    是的,可以在运行时动态生成存根,但很可能需要 300 毫秒以上的时间——我们说的是生成数千个存根。顺便说一句,它需要 DynamicMethods 或 3.5 表达式。

    最好的方法是在编译之前生成存根。理想情况下,生成字段的代码生成器也应该生成存根。如果您无法修改现有的代码生成器,您可能需要使用模板引擎,例如 T4。

    【讨论】:

    • 初始测试表明,反射在初始化委托时明显快于 JIT:反射约为 300 毫秒,而 JIT 代码约为 2500 毫秒。 (很明显,一旦代码被 JITted,表格就会翻转,但我们只关心初始启动时间)。两个测试都使用相同的 LoadDelegate() 方法。如果我使用 DynamicMethods 或表达式,这些存根会是什么样子?我将如何捕获原始参数并在存根内部执行方法?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2011-07-21
    • 2019-01-24
    • 1970-01-01
    相关资源
    最近更新 更多