Comments 12
Я не совсем понял комментарий, вы описали ситуацию когда известен тип аргумента, а значит и известен нужный инстанс. Пост же совсем о другом, я описываю случай когда тип будет неизвестен. И код который вы указали не работает, точнее если его дописать в
то это прямой вызов, бесполезно обернутый анонимной функцией, а не вызов посредством создания делегата метода заранее неизвестного инстанса.
Func<DateTime, long> hook = Container.Get<DateTime>().Process;
то это прямой вызов, бесполезно обернутый анонимной функцией, а не вызов посредством создания делегата метода заранее неизвестного инстанса.
0
Имхо, терминология в статье отличается от классической.
Называемый в статье «вызов через делегат» — в классике «вызов через expression».
Вызов через делегат в классике — это:
Называемый в статье «вызов через делегат» — в классике «вызов через expression».
Вызов через делегат в классике — это:
Func<DateTime, int> f = instance.Process;
for(..){f(arg);}
+4
Expression в коде служит для создания делегата, вызов метода идет именно через вызов делегата.
0
Вызов делегата это delegate(aaa);
А не всякие там GetType() и GetMethod() это тот же рефлекшен только в профиль
А еще есть вызов интерфейсов, вобщем прежде чем писать мегастатьи лучше погуглите codeplex с 2005 годов, много узнаете нового
А не всякие там GetType() и GetMethod() это тот же рефлекшен только в профиль
А еще есть вызов интерфейсов, вобщем прежде чем писать мегастатьи лучше погуглите codeplex с 2005 годов, много узнаете нового
0
Задача описанная в статье, вызов метода у заранее неизвестного инстанса. При этом метод generic. По результатам я пришел к выводу что вызывать лучше всего через dynamic или через оптимизированный вызов делегата.
Если вы знаете как вызвать более оптимально, покажите как. Я пока не нашел решения лучше.
Если вы знаете как вызвать более оптимально, покажите как. Я пока не нашел решения лучше.
0
Нда… так криво вызывать делегат — это надо постараться… нафига писать говнокод. а потом обсуждать, что он плохо работает…
Пишем:
public static TestResult TestDelegateCall(DateTime arg)
{
var instance = Container.Get(arg.GetType());
//var hook = CreateDelegate(instance, instance.GetType().GetMethod(«Process»));
Func hook = Container.Get().Process;
Stopwatch sw = new Stopwatch();
sw.Start();
long summ = 0;
for (long i = 0; i < ITERATION_COUNT; i++)
{
//summ += (long)hook.DynamicInvoke(arg);
summ += hook(arg);
}
sw.Stop();
return new TestResult { Result = summ, ElapsedMilliseconds = sw.ElapsedMilliseconds };
}
И вуаля:
Прямой вызов
Min: 921 ms
Max: 943 ms
Mean: 928,8 ms
Median: 928,5 ms
Вызов через отражение
Min: 1302 ms
Max: 1319 ms
Mean: 1311,3 ms
Median: 1310,5 ms
Вызов через делегат
Min: 921 ms
Max: 940 ms
Mean: 929,2 ms
Median: 929 ms
Вызов через делегат с оптимизациями
Min: 1093 ms
Max: 1117 ms
Mean: 1103,7 ms
Median: 1101,5 ms
Вызов через dynamic
Min: 1058 ms
Max: 1076 ms
Mean: 1066,6 ms
Median: 1065,5 ms
Пишем:
public static TestResult TestDelegateCall(DateTime arg)
{
var instance = Container.Get(arg.GetType());
//var hook = CreateDelegate(instance, instance.GetType().GetMethod(«Process»));
Func hook = Container.Get().Process;
Stopwatch sw = new Stopwatch();
sw.Start();
long summ = 0;
for (long i = 0; i < ITERATION_COUNT; i++)
{
//summ += (long)hook.DynamicInvoke(arg);
summ += hook(arg);
}
sw.Stop();
return new TestResult { Result = summ, ElapsedMilliseconds = sw.ElapsedMilliseconds };
}
И вуаля:
Прямой вызов
Min: 921 ms
Max: 943 ms
Mean: 928,8 ms
Median: 928,5 ms
Вызов через отражение
Min: 1302 ms
Max: 1319 ms
Mean: 1311,3 ms
Median: 1310,5 ms
Вызов через делегат
Min: 921 ms
Max: 940 ms
Mean: 929,2 ms
Median: 929 ms
Вызов через делегат с оптимизациями
Min: 1093 ms
Max: 1117 ms
Mean: 1103,7 ms
Median: 1101,5 ms
Вызов через dynamic
Min: 1058 ms
Max: 1076 ms
Mean: 1066,6 ms
Median: 1065,5 ms
+8
>(long)hook.DynamicInvoke(arg);
Это бесполезный бенчмарк. Реализация Dynamic Invoke идёт через MethodInfo.Invoke() и не отличается от reflection. Вызов делегата это вызов Invoke на нем.
Это бесполезный бенчмарк. Реализация Dynamic Invoke идёт через MethodInfo.Invoke() и не отличается от reflection. Вызов делегата это вызов Invoke на нем.
+5
Даже если типы неизвестны заранее — это еще не повод использовать DynamicInvoke! Раз уж вы используете Expression.Compile() — надо с помощью приведения типов привести делегат к заранее известной сигнатуре.
Вот такой делегат в тесты добавьте, пожалуйста! На моих тестах он работает столь же быстро, как и прямой вызов.
delegate object Invoker(object target, params object[] args);
static Invoker CreateDelegate(MethodInfo method)
{
var targetArg = Expression.Parameter(typeof(object));
var argsArg = Expression.Parameter(typeof(object[]));
Expression body = Expression.Call(
method.IsStatic ? null : Expression.Convert(targetArg, method.DeclaringType),
method,
method.GetParameters().Select((p, i) => Expression.Convert(Expression.ArrayIndex(argsArg, Expression.Constant(i)), p.ParameterType)));
if (body.Type == typeof(void))
body = Expression.Block(body, Expression.Constant(null));
else if (body.Type.IsValueType)
body = Expression.Convert(body, typeof(object));
return Expression.Lambda<Invoker>(body, targetArg, argsArg).Compile();
}
Вот такой делегат в тесты добавьте, пожалуйста! На моих тестах он работает столь же быстро, как и прямой вызов.
+5
Статье не хватает вывода: для чего были все потуги?
Вот тут (по теме) есть выводы: habrahabr.ru/post/103558
Вот тут (по теме) есть выводы: msdn.microsoft.com/library/ms973852.aspx
Вот тут (по теме) есть выводы: habrahabr.ru/post/103558
Вот тут (по теме) есть выводы: msdn.microsoft.com/library/ms973852.aspx
0
Почему бы не использовать для бенчмарков BenchmarkDotNet?
Бенчмарк не учитывает много аспектов, которые учитываются в BenchmarkDotNet.
Почему и как правильно бенчмаркать можно узнать, например,
в котором DreamWalker рассказывает о распространённых ошибках оценки производительности .NET-приложений.
Бенчмарк не учитывает много аспектов, которые учитываются в BenchmarkDotNet.
Почему и как правильно бенчмаркать можно узнать, например,
из вот этого видео,
в котором DreamWalker рассказывает о распространённых ошибках оценки производительности .NET-приложений.
+2
Sign up to leave a comment.
Исследование скорости вызова метода различными способами