5

我来自 Java 编程并转向 C# 编程,我发现了 LINQ 的强大功能。

在我最近的实现中,我注意到我经常在我的代码中使用它(特别是 LINQ to Objects)来避免foreach循环、搜索列表中的元素和执行类似任务。

现在我想知道在大量使用 Linq to Objects 时是否存在一些性能劣势......

4

4 回答 4

26

Linq 比原生 C# 循环慢。
C# 比 C++ 慢。
C++ 比汇编慢。
组装比设计您自己的定制微处理器要慢。

因此,您应该始终设计自己的定制微处理器,而不是使用 Linq .....

是否有性能影响?可能,但在实际测量之前你不会知道多少。它可能足够小,不会很重要,您可以花时间避免 Linq 处理应用程序中通过优化受益的部分。

底线是 - 使用使您最高效的库和框架构建您的应用程序,然后从那里进行优化。您可能会发现应用程序中最慢的部分根本不是 Linq 代码,因此如果您禁止它只是因为它可能比滚动您自己的循环慢,那么您将优化错误的东西。

于 2012-10-26T13:13:46.490 回答
11

为了客观地回答您的问题,LINQ 大量使用了委托和迭代器,它们具有实例化(委托和迭代器)和方法调用(委托调用和MoveNext()迭代器)的开销。现在, a foreach(on a List<T>) 将具有迭代器的开销,但没有委托的开销。所以预计 LINQ 在这里会比foreach.

同样,使用索引器遍历列表[i]预计会更快,因为它也没有迭代器的开销。更快的不是使用List<T>数组而是数组。但即使这样也有数组边界检查的开销(IndexOutOfRangeException如果你试图超出数组边界,就会抛出一个位),并且可以通过指针使用原始内存访问来避免这种情况,或者通过简单地迭代整个列表(for(var i = 0; i < array.Length; i++) { Console.WriteLine(array[i]); }不会有边界检查,因为编译器可以证明这个循环永远不会越界)。

这些是各种迭代方式带来的不同程度的开销。这些间接费用重要吗?如果您正在执行 10,000 x 10,000 矩阵乘法,那么可以。否则,可能不会,除非您已将其测量为(这是一个令人厌烦的旧答案,但同样有效)。

但是,除了这些事实之外,您如何使用它们也很重要。假设您想要一个 1980 年以后出生的客户列表,这些客户来自更大的客户群,并对他们进行进一步处理。如果没有 LINQ,您将几乎被迫foreach使用原始客户列表并创建一个中间列表,将 1980 年之后出生的客户放入其中。使用LINQ,您将不需要节省大量开销的中间列表(创建列表、调用Add在它上面,随着它的增长而调整它的大小几次)并且可能更快。而且它的内存效率肯定更高,因为 1980 年之后出生的客户被一个一个地“流式传输”,而中间列表不会占用内存。使用 LINQ,您可以处理无限长的序列。

使用 LINQ 的另一个性能原因是某些操作的并行化AsParallel()在查询结束时调用变得微不足道。

因此,如果使用 LINQ 存在性能劣势,请回答您的问题:

这取决于。

于 2012-10-26T21:21:45.610 回答
0

从广义上讲,LINQ 没有提供任何性能优势,但它的某些实现可能会。如果您想要高性能代码,那么您仍然需要广泛了解每个 LINQ 查询的算法时间复杂度。

例如,我见过的一个常见场景是针对特定值对列表执行 WHERE 子句,这将导致扫描列表中的项目,这将具有 O(n) 复杂度。Dictionary<K,V>如果您维护一个哈希表(例如)来执行查找,那么这样的操作当然可以用 O(1) 复杂度来实现。

于 2012-10-26T13:14:47.783 回答
0

对于任何你失去控制并且必须依赖于你不知道底层代码的实现的抽象,性能往往会变慢(因为 LINQ 必须是通用的,并且不能以牺牲为代价对一种类型的对象进行完全优化另一个)。但是多少取决于你的情况。例如,如果您的应用程序每天被命中数百万次并且您需要绝对性能,那么使用 LINQ 到实体进行数据库查询可能不是一个好主意,您可能希望对 LINQ 不允许您执行的 SQL 查询进行性能优化做。但是,如果您的应用程序用作用户数量相对较少的企业应用程序的一部分,那么您可能可以大量使用 LINQ。所以我的回答是肯定的,它会变慢,

于 2012-10-26T13:02:14.913 回答