我正在使用各种 lambda 表达式语法测试性能差异。如果我有一个简单的方法:
public IEnumerable<Item> GetItems(int point)
{
return this.items.Where(i => i.IsApplicableFor(point));
}
然后这里有一些与point
参数相关的变量提升,因为从 lambda 的角度来看,它是一个自由变量。如果我将这个方法调用一百万次,是保持原样还是以任何方式更改它以提高其性能会更好吗?
我有哪些选择,哪些实际上可行?据我了解,我必须摆脱自由变量,因此编译器不必创建闭包类并在每次调用此方法时实例化它。与非封闭版本相比,这种实例化通常需要大量时间。
问题是我想提出一些通常可以工作的lambda 编写指南,因为每次我编写一个深受打击的 lambda 表达式时,我似乎都在浪费一些时间。我必须手动测试它以确保它可以工作,因为我不知道要遵循什么规则。
替代方法
& 示例控制台应用程序代码
我还编写了不需要任何变量提升的相同方法的不同版本(至少我认为不需要,但如果是这样的话,理解这一点的人请告诉我):
public IEnumerable<Item> GetItems(int point)
{
Func<int, Func<Item, bool>> buildPredicate = p => i => i.IsApplicableFor(p);
return this.items.Where(buildPredicate(point));
}
在这里查看要点。只需创建一个控制台应用程序并将整个代码复制到块Program.cs
内的文件中namespace
。您将看到第二个示例要慢得多,即使它不使用自由变量。
一个矛盾的例子
我想构建一些lambda 最佳使用指南的原因是我以前遇到过这个问题,令我惊讶的是,当使用谓词构建器lambda 表达式时,一个工作得更快。
现在解释一下。我在这里完全迷失了,因为当我知道我的代码中有一些大量使用方法时,我可能根本不会使用 lambdas。但我想避免这种情况并深入了解这一切。
编辑
您的建议似乎不起作用
我尝试实现一个自定义查找类,它在内部工作类似于编译器对自由变量 lambda 所做的工作。但是我没有实现闭包类,而是实现了模拟类似场景的实例成员。这是代码:
private int Point { get; set; }
private bool IsItemValid(Item item)
{
return item.IsApplicableFor(this.Point);
}
public IEnumerable<TItem> GetItems(int point)
{
this.Point = point;
return this.items.Where(this.IsItemValid);
}
有趣的是,它的运行速度与慢速版本一样慢。我不知道为什么,但它似乎除了快速之外什么也没做。它重用了相同的功能,因为这些附加成员是同一个对象实例的一部分。反正。我现在非常困惑!
我已经用这个最新的添加更新了Gist 源,所以你可以自己测试。