2009-10-21 7 views
0

Проблемы:Использование отражение заглушки для инициализации поля делегата лениво

  • класса .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); 
     } 
    } 
} 

У меня есть ощущение, что это является можно создать заглушку, которая выполняет (а), (б) и (в), но я не сумел предугадать, как .

В идеале код должен работать .Net 2.0 и Mono 2.0 и должен не использовать System.Reflection.Emit. Однако меня также будут интересовать решения с использованием .Net 3.5 или DynamicMethod.

Любые идеи? :)

ответ

1

Да, можно динамически генерировать заглушки во время выполнения, но очень вероятно, что потребуется больше 300 мс - мы говорим о создании тысяч заглушек. И, кстати, для этого потребуются DynamicMethods или, возможно, 3.5 выражения.

Лучшим подходом было бы создание заглушек перед компиляцией. В идеале генератор кода, который генерирует поля, должен также генерировать заглушки. Если вы не можете изменить существующий генератор кода, вы можете использовать механизм шаблонов, например T4.

+0

Начальные испытания показали, что отражение значительно быстрее, чем JIT при инициализации делегатов: ~ 300 мс для отражения против ~ 2500 мс для JIT-кода. (Очевидно, что таблицы поворачиваются, когда код JITted, но мы имеем дело только с начальным временем запуска). Оба теста использовали один и тот же метод LoadDelegate(). Если бы я использовал DynamicMethods или выражения, как бы выглядели эти заглушки? Как я могу захватить исходные параметры и выполнить метод внутри самого заглушки? – BlackStar