我来自Java编程并转而使用C#编程我发现了LINQ的极端强大功能。
在我最近的实现中,我注意到我在代码中经常使用它(特别是LINQ to Objects)以避免foreach
循环,搜索列表中的元素以及类似的任务。
现在我想知道在大量使用Linq to Objects ...
时是否存在一些性能劣势答案 0 :(得分:26)
Linq比原生C#循环慢
C#比C ++慢。
C ++比汇编慢
装配比设计自定义微处理器慢。
因此,您应该始终设计自己的自定义微处理器,而不是使用Linq .....
是否有性能受损?可能,但在实际衡量之前,你不会知道多少。它可能足够小,不会很重要,您可以花费时间来避免Linq通过优化来解决做带来的应用程序部分。
底线是 - 使用最有效率的库和框架构建您的应用程序,然后从那里进行优化。您可能会发现应用程序中最慢的部分根本不是Linq代码,因此如果您因为可能慢于滚动自己的速度而禁止它,那么您将优化错误的东西环路。
答案 1 :(得分:11)
为了客观地回答你的问题,LINQ大量使用委托和迭代器,它们具有实例化(委托和迭代器)和方法调用(在迭代器上委托调用和MoveNext()
)的开销。现在,foreach
(在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存在性能劣势,请回答您的问题:
取决于。
答案 2 :(得分:0)
对于任何放松控制并且必须依赖于您不了解底层代码的实现的抽象,存在性能降低的趋势(因为LINQ必须是通用的,并且不能针对一种类型的对象进行完全优化以牺牲另一个为代价)。但是多少取决于你的情况。例如,如果您的应用程序每天被击中数百万次并且您需要绝对性能,那么使用LINQ to实体进行数据库查询可能不是一个好主意,您可能希望对LINQ不允许您的SQL查询执行性能优化做。但是,如果您的应用程序被用作企业应用程序的一部分,其中用户数量相对较少,那么您可能会大量使用LINQ。所以我的回答是肯定会慢一点,但是因为你的情况可能并不重要。
答案 3 :(得分:0)
从广义上讲,LINQ没有提供性能优势,但可能会有一些实现。如果您需要高性能代码,那么您仍然需要广泛了解每个LINQ查询的算法时间复杂度。
E.g。我见过的一个常见场景是在列表中为特定值执行WHERE子句,这将导致扫描列表中的项,这将具有O(n)复杂度。如果你维护一个哈希表(例如Dictionary<K,V>
)来执行查找,那么这样的操作当然可以用O(1)复杂度来实现。