【问题标题】:Is Linq Faster, Slower or the same?Linq 更快、更慢还是一样?
【发布时间】:2017-07-13 14:51:51
【问题描述】:

这是:

Box boxToFind = AllBoxes.FirstOrDefault(box => box.BoxNumber == boxToMatchTo.BagNumber);

比这更快或更慢:

Box boxToFind ;
foreach (Box box in AllBoxes)
{
    if (box.BoxNumber == boxToMatchTo.BoxNumber)
    {
        boxToFind = box;
    }
}

两者都给我我正在寻找的结果 (boxToFind)。这将在我需要注意性能的移动设备上运行。

【问题讨论】:

  • 您的第一个方法无法编译。 Where 返回一个 IEnumerable。为了等同于最后一个,您必须执行 AllBoxes.Last(box => ...)
  • 好点。我改变了我的第一种方法。 (虽然我没有使用 last,因为它“应该”只有唯一值)
  • 您的第二种方法将编译,但会给您最后一个匹配的框。休息一下;当你退出 if 时。
  • 编辑后,两者实际上并没有做同样的事情。一旦找到第一个匹配框,就应该跳出 foreach 循环。否则,您要么得到不同的结果,要么如果该框是唯一的,您会无缘无故地迭代其余项目,从而降低性能。
  • 正如 Chris Taylor 所说,您自己的实现是“最后一个或默认”,而不是“第一个或默认”。

标签: c# linq performance


【解决方案1】:

应该差不多,只是你需要调用First(或者,为了匹配你的代码,Last),而不是Where
调用Where 会给你一组匹配项(IEnumerable<Box>);你只想要一个匹配的项目。

通常,在使用 LINQ 时,您需要注意延迟执行。在您的特定情况下,这无关紧要,因为您得到的是单个项目。

【讨论】:

  • FirstOrDefault 避免异常
  • @hunter:除非他想要例外。
  • @SLaks 或者知道合适的元素总是存在的。
【解决方案2】:

除非您通过分析确定此特定循环是性能瓶颈,否则差异并不重要。

如果分析确实发现它是一个问题,那么您将需要研究备用存储。将数据存储在字典中,这样查找速度比遍历数组更快。

【讨论】:

  • 字典比数组提供更快的查找?它肯定不会。字典由数组支持,每次访问元素时都会进行额外的计算。因此,字典不可能在迭代中比数组快。
  • @Rubys - 字典查找是 O(1),遍历一个数组是 O(n),因此对于足够大的集合(假设一个合理的哈希函数),字典查找会更快。
  • @Rubys,字典由数组数组支持。哈希码用于准确识别要检索的第一个数组中的哪个元素。没有循环,只是一个简单的数学计算。这为您提供了第二个数组,通常称为存储桶。然后代码循环遍历桶以找到确切的项目。一个好的集合大小和哈希码将导致桶中只有几个项目。最终结果是字典比数组循环快得多。
  • @Rubys:我觉得你有点搞混了。访问数组中已知索引处的项目尽可能快,是的。 枚举数组以发现该索引快。字典通过利用哈希函数来尝试绕过慢速部分(枚举)并直接跳转到快速部分(按索引访问)。
  • 两种选择:我理解错了,或者你理解错了。你是三岁,所以我倾向于认为是前者。枚举整个字典比枚举整个数组更快吗?如果你不知道项目的位置,在字典上查找会更快,但他可能已经相当简化了这个例子,在实际的方法中你必须进行某种计算,或者它可以是任何东西。它现在的形式,当然,字典,但并不总是可能的
【解决方案3】:

如果你喜欢微优化,LINQ 的表现会更差,this is just one article,你可以找到很多其他帖子。

【讨论】:

  • 未成熟的优化是万恶之源。这极不可能与他有关。
  • 不知道您是否阅读了该文章的 cmets,但问题的主要部分不是迭代,而是他原始代码中的隐式转换。 Anders Hejlsberg 指出,不涉及每次迭代强制转换操作的查询与 for 循环相当接近。
【解决方案4】:

微优化会害死你。
首先,完成整个课程,然后,如果您有性能问题,请运行分析器并检查应用程序的热点。
确保您使用了最好的算法,然后转向像这样的微优化。

如果你已经这样做了:
慢 -> 快
LINQ 抽象会使您的代码在 95% 的情况下变慢。

【讨论】:

    【解决方案5】:

    最快的是当你使用 for 循环时。但是差异是如此之小,以至于您忽略了它。仅在构建实时应用程序时才重要,但对于这些应用程序,C# 可能不是最佳选择!

    【讨论】:

      【解决方案6】:

      如果 AllBoxes 是 IQueryable,它可能比循环更快,因为可查询对象可以具有 Where 操作的优化实现(例如索引访问)。

      【讨论】:

      • @Sam:IQueryable 继承了 IEnumerable,所以 foreach 循环有效
      【解决方案7】:

      LINQ 绝对慢 100%

      取决于你想在你的程序中完成什么,但在大多数情况下,这肯定是我所说的懒惰程序代码......

      如果您正在执行任何复杂的查询、连接等,您将基本上“停顿”......这些类型的函数/方法的总 p.o.s - 只是不要使用它。如果您以艰难/漫长的方式做到这一点,从长远来看,您会更快乐……性能将是天壤之别。

      注意

      对于为速度/同步任务/计算而构建的任何程序,我绝对不会推荐 LINQ (即 HFT 交易和/或 AT 交易 i-0-i 对于初学者)。

      已测试

      在“LINQ”中完成一个联接需要将近 10 秒,而

      【讨论】:

        【解决方案8】:

        LINQ 与循环 - 性能测试

        LINQ: 00:00:04.1052060, avg. 00:00:00.0041052
        Loop: 00:00:00.0790965, avg. 00:00:00.0000790
        

        参考资料:

        http://ox.no/posts/linq-vs-loop-a-performance-test

        http://www.schnieds.com/2009/03/linq-vs-foreach-vs-for-loop-performance.html

        【讨论】:

        • 这个问题问的是一个特定的查询,你的答案是完全不同的。
        猜你喜欢
        • 1970-01-01
        • 2015-04-07
        • 2010-11-02
        • 2020-11-13
        • 1970-01-01
        • 2010-12-21
        • 2015-10-22
        • 1970-01-01
        • 2012-02-14
        相关资源
        最近更新 更多