Я ожидал бы, что делегаты, сгенерированные из деревьев выражений, достигнут примерно той же производительности, что и жестко закодированные статические эквивалентные анонимные методы.Однако кажется, что динамически генерируемые делегаты заметно медленнее ...
Вот простая тестовая программа, иллюстрирующая ситуацию.Он просто получает 3 свойства объекта 1000000 раз:
static void Main()
{
var foo = new Foo { A = 42, B = "Hello world", C = new DateTime(1970, 1, 1) };
Func<Foo, int> getA;
Func<Foo, string> getB;
Func<Foo, DateTime> getC;
// Using hard-coded lambdas
getA = f => f.A;
getB = f => f.B;
getC = f => f.C;
Console.WriteLine("Hard-coded: {0}", Test(foo, getA, getB, getC));
// Using dynamically generated delegates
ParameterExpression prm = Expression.Parameter(typeof(Foo), "foo");
getA = Expression.Lambda<Func<Foo, int>>(Expression.Property(prm, "A"), prm).Compile();
getB = Expression.Lambda<Func<Foo, string>>(Expression.Property(prm, "B"), prm).Compile();
getC = Expression.Lambda<Func<Foo, DateTime>>(Expression.Property(prm, "C"), prm).Compile();
Console.WriteLine("Generated: {0}", Test(foo, getA, getB, getC));
}
const int N = 1000000;
static TimeSpan Test(Foo foo, Func<Foo, int> getA, Func<Foo, string> getB, Func<Foo, DateTime> getC)
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
getA(foo);
getB(foo);
getC(foo);
}
sw.Stop();
return sw.Elapsed;
}
public class Foo
{
public int A { get; set; }
public string B { get; set; }
public DateTime C { get; set; }
}
Я последовательно получаю результаты, показывающие, что жестко запрограммированные лямбды примерно в 6 раз быстрее:
Hard-coded: 00:00:00.0115959
Generated: 00:00:00.0735896
Hard-coded: 00:00:00.0113993
Generated: 00:00:00.0648543
Hard-coded: 00:00:00.0115280
Generated: 00:00:00.0611804
Может кто-нибудь объяснить эти результаты?Это из-за оптимизации компилятора?или JIT-оптимизации?
Спасибо за ваше понимание
РЕДАКТИРОВАТЬ: я запускал свои тесты с LINQPad, который компилируется с включенной оптимизацией.Когда я запускаю одни и те же тесты в VS с отключенной оптимизацией, я получаю примерно одинаковые результаты в обоих случаях.Таким образом, кажется, что компилятор просто вставлял доступ к свойству в жестко запрограммированные лямбды ...
Дополнительный вопрос: есть ли способ оптимизировать код, сгенерированный из деревьев выражений?