简体   繁体   English

使用“大量”LINQ to Objects语句有什么缺点吗?

[英]Are there some disadvantages in using “a lot” of LINQ to Objects statements?

I come from Java programming and switching to C# programming I discovered the extreme powerful of LINQ. 我来自Java编程并切换到C#编程我发现了LINQ的极端强大功能。

In my recent implementation I noticed that I use it (expecially LINQ to Objects) very often in my code to avoid foreach loops, to search elements in lists and for similar tasks. 在我最近的实现中,我注意到我经常在我的代码中使用它(特别是LINQ to Objects)来避免foreach循环,搜索列表中的元素以及类似的任务。

Now I'm wondering if there is some performance disadvantage in massively use Linq to Objects... 现在我想知道在大量使用Linq to Objects时是否存在一些性能劣势......

Linq is slower than native C# loops. Linq比本机C#循环慢。
C# is slower than C++. C#比C ++慢。
C++ is slower than assembly. C ++比程序集慢。
Assembly is slower than designing your own custom microprocessor. 装配比设计自定义微处理器慢。

So you should always design your own custom microprocessor instead of using Linq..... 所以你应该总是设计自己的定制微处理器,而不是使用Linq .....

Is there a performance hit? 是否有性能受损? Probably, but you won't know how much until you actually measure it . 可能,但在实际测量它之前你不会知道多少。 It may be small enough that it won't be significant and you can spend the time you would have spent avoiding Linq tackling the parts of the application that do benefit by optimization. 这可能是足够小,它不会很显著,你可以花,你将花费避免LINQ的应对应用程序,它通过优化的好处部分的时间。

Bottom line is - build your app using the libraries and frameworks that make you the most productive, then optimize from there. 底线是 - 使用最有效率的库和框架构建您的应用程序,然后从那里进行优化。 You may find out that the slowest part of your app isn't the Linq code at all, so you'd be optimizing the wrong thing if you forbade it just because it might be slower than rolling your own loops. 您可能会发现应用程序中最慢的部分根本不是Linq代码,所以如果您因为它可能比滚动自己的循环更慢而禁止它,那么您将优化错误的东西。

To answer your question objectively, LINQ makes heavy use of delegates and iterators, which has the overhead of instantiations (delegates and iterators) and method calls (delegate invocation and MoveNext() on iterators). 为了客观地回答你的问题,LINQ大量使用委托和迭代器,它们具有实例化(委托和迭代器)和方法调用(迭代器上的委托调用和MoveNext()的开销。 Now, a foreach (on a List<T> ) will have the overhead of the iterator, but not the overhead of delegates. 现在, foreach (在List<T> )将具有迭代器的开销,但不会占用委托的开销。 So it's expected that LINQ will be slower here than a foreach . 所以预计LINQ在这里会比foreach慢。

Likewise, iterating through the list using the [i] indexer is expected to be faster still because it also doesn't have the overhead of the iterator. 同样,使用[i]索引器迭代列表预计会更快,因为它也没有迭代器的开销。 Even faster is not using a List<T> but an array. 更快的是不使用List<T>而是使用数组。 But even that has the overhead of array bounds checks (the bit that throws an IndexOutOfRangeException if you try to go outside array bounds) and that can be avoided by using raw memory access through pointers, or by simply iterating the entire list ( for(var i = 0; i < array.Length; i++) { Console.WriteLine(array[i]); } won't have bounds checks because the compiler can prove this loop will never go out of bounds). 但是,即便是有数组的开销边界检查(即抛出位IndexOutOfRangeException并且可以使用通过指针原始内存访问来可以避免的,如果你试图去外面数组边界),或通过简单地遍历整个列表( for(var i = 0; i < array.Length; i++) { Console.WriteLine(array[i]); }将没有边界检查,因为编译器可以证明此循环永远不会超出范围)。

Those are the varying degrees of overhead that the various ways of iteration bring with them. 这些是各种迭代方式带来的不同程度的开销。 Do those overheads matter? 那些管理费用是否重要? If you're doing 10,000 x 10,000 matrix multiplication, then yes. 如果您正在进行10,000 x 10,000矩阵乘法,那么是。 Otherwise, probably not unless you've measured it to be (which is a tired old answer, but no less valid). 否则,可能不会,除非你已经测量过它(这是一个疲惫不堪的旧答案,但同样有效)。

However, aside from those facts it also matters how you use them. 但是,除了这些事实之外,你如何使用它们也很重要。 Say you want a list of customers who were born after 1980 from a larger pile of customers and do further processing on them. 假设您想要一个1980年以后出生的客户列表,这些客户来自更多的客户并对其进行进一步处理。 Without LINQ, you be would pretty much forced to foreach the original customer list and create an intermediate list that you put the customers who were born after 1980 into. 没有LINQ,你可以将几乎被迫foreach原来的客户名单,并创建你把谁是1980年出生后到客户中间清单。 With LINQ, you won't need the intermediate list which saves quite a lot of overhead (creating the list, calling Add on it, resizing it several times most likely as it grows) and is likely to be faster. 使用 LINQ,您将不需要中间列表,这可以节省相当多的开销(创建列表,调用Add on it,在其增长时最多可能调整几次)并且可能更快。 And it's certainly more memory efficient, as the customers born after 1980 are 'streamed' in one by one without the intermediate list taking up memory. 而且它的内存效率肯定更高,因为1980年以后出生的客户一个接一个地“流式传输”而没有中间列表占用内存。 With LINQ, you can potentially process an infinitely long sequence. 使用LINQ,您可以处理无限长的序列。

Another performance reason to use LINQ is that parallelization of certain operations becomes trivial with the AsParallel() call at the end of a query. 使用LINQ的另一个性能原因是,在查询结束时使用AsParallel()调用,某些操作的并行化变得微不足道。

So to answer your question if there's a performance disadvantage to using LINQ: 因此,如果使用LINQ存在性能劣势,请回答您的问题:

It depends. 这取决于。

With any abstraction where you loose control and have to depend on implementations where you are not aware of the underlying code there is a tendency to have slower performance (because LINQ has to be generic and cannot be fully optimized for one type of object at the expense of another). 对于任何放松控制的抽象而且必须依赖于您不了解底层代码的实现,存在性能降低的趋势(因为LINQ必须是通用的,并且不能完全针对一种类型的对象进行优化而需要付出代价另一个)。 However how much depends on your situation. 但是多少取决于你的情况。 For example if your application is hit millions of times per day and you need absolute performance then using LINQ to entities for database queries is probably not a great idea, you may want to do performance optimizations on your SQL queries that LINQ will not allow you to do. 例如,如果您的应用程序每天被击中数百万次并且您需要绝对性能,那么使用LINQ to实体进行数据库查询可能不是一个好主意,您可能希望对LINQ不允许您的SQL查询执行性能优化做。 But if your application is used as part of an enterprise application where the number of users is relatively small then you're probably ok with using LINQ heavily. 但是,如果您的应用程序被用作企业应用程序的一部分,其中用户数量相对较少,那么您可能会大量使用LINQ。 So my answer is yes it's going to be slower, but it may not matter because of your situation. 所以我的回答是肯定会慢一点,但是因为你的情况可能并不重要。

Broadly speaking LINQ offers no performance benefits, but some implementations of it might. 从广义上讲,LINQ没有提供性能优势,但可能会有一些实现。 If you want performant code then you still need to have a broad awareness of the algorithmic time complexity of each LINQ query. 如果您需要高性能代码,那么您仍然需要广泛了解每个LINQ查询的算法时间复杂度。

Eg a common scenario I've seen is to perform a WHERE clause over a list for a specific value, which will cause a scan of the items in the list, which will have O(n) complexity. 例如,我见过的常见情况是在列表上为特定值执行WHERE子句,这将导致扫描列表中的项目,这将具有O(n)复杂度。 Such an operation can of course be achieved with O(1) complexity if you maintain a hash table (eg Dictionary<K,V> ) to perform the lookups against. 如果你维护一个哈希表(例如Dictionary<K,V> )来执行查找Dictionary<K,V>那么这样的操作当然可以用O(1)复杂度来实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM