考虑对集合进行以下简单操作:
static List<int> x = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var result = x.Where(i => i % 2 == 0).Where(i => i > 5);
现在让我们使用表达式:
static void UsingLambda() {
Func<IEnumerable<int>, IEnumerable<int>> lambda = l => l.Where(i => i % 2 == 0).Where(i => i > 5);
var t0 = DateTime.Now.Ticks;
for (int j = 1; j < MAX; j++)
var sss = lambda(x).ToList();
var tn = DateTime.Now.Ticks;
Console.WriteLine("Using lambda: {0}", tn - t0);
}
但我想在运行中构建这个表达式,所以这里有一个新的测试:
static void UsingCompiledExpression() {
var f1 = (Expression<Func<IEnumerable<int>, IEnumerable<int>>>)(l => l.Where(i => i % 2 == 0));
var f2 = (Expression<Func<IEnumerable<int>, IEnumerable<int>>>)(l => l.Where(i => i > 5));
var argX = Expression.Parameter(typeof(IEnumerable<int>), "x");
var f3 = Expression.Invoke(f2, Expression.Invoke(f1, argX));
var f = Expression.Lambda<Func<IEnumerable<int>, IEnumerable<int>>>(f3, argX);
var c3 = f.Compile();
var t0 = DateTime.Now.Ticks;
for (int j = 1; j < MAX; j++)
var sss = c3(x).ToList();
var tn = DateTime.Now.Ticks;
Console.WriteLine("Using lambda compiled: {0}", tn - t0);
}
当然,它并不完全像上面那样,所以为了公平起见,我稍微修改了第一个:
static void UsingLambdaCombined() {
Func<IEnumerable<int>, IEnumerable<int>> f1 = l => l.Where(i => i % 2 == 0);
Func<IEnumerable<int>, IEnumerable<int>> f2 = l => l.Where(i => i > 5);
Func<IEnumerable<int>, IEnumerable<int>> lambdaCombined = l => f2(f1(l));
var t0 = DateTime.Now.Ticks;
for (int j = 1; j < MAX; j++)
var sss = lambdaCombined(x).ToList();
var tn = DateTime.Now.Ticks;
Console.WriteLine("Using lambda combined: {0}", tn - t0);
}
现在来看 MAX = 100000,VS2008,调试 ON 的结果:
Using lambda compiled: 23437500
Using lambda: 1250000
Using lambda combined: 1406250
关闭调试:
Using lambda compiled: 21718750
Using lambda: 937500
Using lambda combined: 1093750
令人惊讶的是,编译后的表达式大约比其他替代方法慢17倍,现在问题来了:
l.Where(i => i % 2 == 0).Where(i => i > 5);
?更多统计数据。 VisualStudio2010,调试打开,优化关闭:
Using lambda: 1093974
Using lambda compiled: 15315636
Using lambda combined: 781410
调试,优化:
Using lambda: 781305
Using lambda compiled: 15469839
Using lambda combined: 468783
关闭调试,优化:
Using lambda: 625020
Using lambda compiled: 14687970
Using lambda combined: 468765
从 VS2008(C # 3)切换到 VS2010(C # 4) ,使得 UsingLambdaCombined
比本地 lambda 更快。
好的,我已经找到了一种方法,可以将 lambda 编译的性能提高一个数量级以上。这里有一个提示; 在运行了分析器之后,92% 的时间都花在了:
System.Reflection.Emit.DynamicMethod.CreateDelegate(class System.Type, object)
嗯... ... 为什么它要在每次迭代中创建一个新的委托?我不确定,但是解决方案在另一篇文章中提出。