Проблемы:Использование отражение заглушки для инициализации поля делегата лениво
класса .NET 2.0 с нескольких тысяч делегатами полей, генерируемого генератором кода
- различных подписями
- Делегаты могут или не могут возвращать значения
- нет дженериков
эти делегаты очень быстро инициализируется во время выполнения
- инициализации делегата является простой, но дорогой
- инициализацией целые затраты лота ~ 300мс прямо сейчас - приемлемо, но не идеально
- в пользователь, скорее всего, будет использовать менее 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.
Любые идеи? :)
Начальные испытания показали, что отражение значительно быстрее, чем JIT при инициализации делегатов: ~ 300 мс для отражения против ~ 2500 мс для JIT-кода. (Очевидно, что таблицы поворачиваются, когда код JITted, но мы имеем дело только с начальным временем запуска). Оба теста использовали один и тот же метод LoadDelegate(). Если бы я использовал DynamicMethods или выражения, как бы выглядели эти заглушки? Как я могу захватить исходные параметры и выполнить метод внутри самого заглушки? – BlackStar