如何最佳地优化或“调整”LINQ表达式?

3
构建LINQ表达式(对我来说是linq to objects)有很多方法可以完成某些任务,其中一些比其他方法更好、更有效。
- 有没有一种好的方法来“调整”或优化这些表达式? - 人们使用哪些基本指标以及如何收集它们? - 是否有一种方法可以获取“总迭代次数”或其他指标,从而可以“知道”较低的意味着更好?
编辑:
感谢Richard / Jon的答案。
看起来我真正想要的是一种获得LINQ表达式的简单操作计数“OCount”的方法,但我不确定LINQ中是否存在这样的钩子。假设我有一个特定机器硬件的目标性能级别(SLA)。理想情况下,我将添加一个单元测试,以确认通过该查询移动的典型数据将在分配的时间范围内(从SLA)处理(接近SLA)。问题在于,这将在构建服务器/开发者机器等上运行,这些机器可能与SLA的目标机器硬件差异很大。因此,我的想法是,我将确定表达式的可接受最大“OCount”,如果OCount小于X,则在目标“典型”硬件上肯定会提供可接受的性能。如果OCount超过此阈值,则构建/单元测试将生成警告。理想情况下,我希望有类似以下的东西(伪代码):
var results = [big linq expression run against test dataset];
Assert.IsLess(MAXALLOWABLE_OCOUNT, results.OCount)

其中,results.OCount 只会给出生成结果集所需的总迭代次数(n)。

为什么我需要这个?

哪怕是一个中等大小的LINQ表达式,稍加更改或添加都可能对性能产生巨大影响,因为整体操作次数增加了。应用程序代码仍然可以通过所有单元测试,因为它仍然会生成正确的结果,但在部署时运行速度非常慢。

另一个原因是为了简单学习。如果你做了某些事情,OCount增加或减少一个数量级,那么你就学到了一些东西。

编辑#2 我还会提供一个潜在的答案。这不是我的答案,而是来自Cameron MacFarland的另一个问题的答案,该问题引发了这个问题。事实证明,我认为那个问题的答案也适用于像我在第一个编辑中描述的单元测试环境。

其本质是在单元测试夹具中创建测试数据集,按照本答案中概述的方式将其馈送到LINQ表达式中,然后将迭代计数相加并与最大允许迭代计数进行比较。

请参见Cameron的答案

3个回答

6
你基本上需要计算复杂度函数。这取决于运算符,但不幸的是通常没有很好的记录文档。
(对于一般原则,我同意Richard的答案 - 这只是LINQ到对象的东西。)
如果你有特定的运算符感兴趣,询问它们会很值得,但是脑海中:
- Select = O(n) - Where = O(n) - Join = O(inner + outer + matches)(即它不比inner+outer更便宜,但根据结果可能像inner*outer那样糟糕) - GroupJoin = 与Join相同,但由外部缓冲而不是流式处理 - OrderBy = O(n log n) - SelectMany = O(n + results) - Count = O(1)或O(n),具体取决于它是否实现了IList - Count(predicate) = O(n) - Max / Min = O(n) - All / Any = O(n)(可能提前结束) - Distinct = O(n) - Skip / Take = O(n) - SkipWhile / TakeWhile = O(n)
确切的特性取决于运算符是否缓冲或流式处理。

3
  1. 获取一个SLA(或其他定义),描述所需的整体性能。

  2. 测量应用程序的性能,以及它距离要求有多远(如果在要求范围内,则停止并做些有用的事情)。

  3. 使用分析器获取详细的性能分析结果,识别系统中最需要改进的部分(对热门代码进行小幅度改进可能比对很少被调用的代码进行大幅度改进更好)。

  4. 进行更改,重新运行单元/功能测试(快速执行错误的操作没有意义)。

  5. 回到步骤1。

如果在步骤3中发现LINQ表达式是性能问题,则需要考虑需要回答以下问题。答案完全取决于您使用的LINQ提供程序以及其在您的情况下的使用细节。没有通用答案。


0

在Jon的基础上,又有了Richard的补充。

另一个需要考虑的问题是是否处理LINQ查询的所有结果。在某些情况下,特别是UI方面,您最终只会处理从LINQ查询返回的一部分结果。在这种情况下,了解哪些LINQ查询支持惰性评估非常重要。也就是说,能够返回结果的子集而不必处理整个集合。

例如,在以下LINQ操作中调用MoveNext()将逐个处理一个结果:

  • Select
  • Where

但是以下操作必须在返回单个项目之前处理集合中的每个元素。

  • OrderBy
  • Except(完全处理其他集合)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接