Nested foreach vs lambda/linq query performance(LINQ-to-Objects)
Write the clearest code you can, and then benchmark and profile to discover any performance problems. If you do have performance problems, you can experiment with different code to work out whether it's faster or not (measuring all the time with as realistic data as possible) and then make a judgement call as to whether the improvement in performance is worth the readability hit.
A direct foreach
approach will be faster than LINQ in many cases. For example, consider:
var query = from element in list
where element.X > 2
where element.Y < 2
select element.X + element.Y;
foreach (var value in query)
{
Console.WriteLine(value);
}
Now there are two where
clauses and a select
clause, so every eventual item has to pass through three iterators. (Obviously the two where clauses could be combined in this case, but I'm making a general point.)
Now compare it with the direct code:
foreach (var element in list)
{
if (element.X > 2 && element.Y < 2)
{
Console.WriteLine(element.X + element.Y);
}
}
That will run faster, because it has fewer hoops to run through. Chances are that the console output will dwarf the iterator cost though, and I'd certainly prefer the LINQ query.
EDIT: To answer about "nested foreach" loops... typically those are represented with SelectMany
or a second from
clause:
var query = from item in firstSequence
from nestedItem in item.NestedItems
select item.BaseCount + nestedItem.NestedCount;
Here we're only adding a single extra iterator, because we'd already be using an extra iterator per item in the first sequence due to the nested foreach
loop. There's still a bit of overhead, including the overhead of doing the projection in a delegate instead of "inline" (something I didn't mention before) but it still won't be very different to the nested-foreach performance.
This is not to say you can't shoot yourself in the foot with LINQ, of course. You can write stupendously inefficient queries if you don't engage your brain first - but that's far from unique to LINQ...
Code performance on double for loop compare to linq/lambda
Both statements are equal on their complexity, namely O(n^2)
. Internally the ForEach
-statement will create a simply loop doing what is determined by the lambda-statement. So the total number of calls to the inner code is the same making both approaches similar in their complexity.
Anyway to get meaningful results on your actual time-performance you should use some profiling-tools, e.g. Resharper. Alternatively simply add some Stopwatch statements into your code to measure how long things need to proceed.
Is a LINQ statement faster than a 'foreach' loop?
Why should LINQ be faster? It also uses loops internally.
Most of the times, LINQ will be a bit slower because it introduces overhead. Do not use LINQ if you care much about performance. Use LINQ because you want shorter better readable and maintainable code.
For vs. Linq - Performance vs. Future
The best practice depends on what you need:
- Development speed and maintainability: LINQ
- Performance (according to profiling tools): manual code
LINQ really does slow things down with all the indirection. Don't worry about it as 99% of your code does not impact end user performance.
I started with C++ and really learnt how to optimize a piece of code. LINQ is not suited to get the most out of your CPU. So if you measure a LINQ query to be a problem just ditch it. But only then.
For your code sample I'd estimate a 3x slowdown. The allocations (and subsequent GC!) and indirections through the lambdas really hurt.
Replacing nested foreach with LINQ; modify and update a property deep within
LINQ is not intended to modify sets of objects. You wouldn't expect a SELECT sql statement to modify the values of the rows being selected, would you? It helps to remember what LINQ stands for - Language INtegrated Query. Modifying objects within a linq query is, IMHO, an anti-pattern.
Stan R.'s answer would be a better solution using a foreach loop, I think.
Nested foreach loops to LINQ
The first part isn't so easy to convert because of the conditional EarningsList.Add()
But You can rewrite the last 2 rather easily.
Assuming that AddMoney()
does just what it says, you can use Sum()
. Otherwise, omit the Sum() and run a separate foreach on the list of amounts. That would make it a lot less Linq.
var amount = ProductList
.SelectMany(item => item.Products)
.Where(product => product.EmployeeName == employee.Name && product.EmployeeLastName == employee.LastName)
.Sum(product => product.Count * product.Price)
;
earnings.AddMoney(amount);
Lambda - Nested forEach operations on multiple ListT very slow
As in the comments above:
It looks like in your
callQuery.Where
calls, you are filtering by
whether it's a holiday or not. You can do this beforehand outside the
dataCopy.ForEach
loop and make two filtered lists. Then you won't
have to loop over all 792 in the inner loop.
It seems this worked well for you! :) If you need to get it lower than 1.25 seconds you are probably going to have to do what @Alexei Levenkov suggested and start making dictionaries of your data.
How would I optimize a nested for loop with linq
var query = from to in allCurrentTradeObjects
from ro in theseWantMe
where ro.Type == to.Type &&
ro.MaxRent >= to.Rent &&
ro.MinRooms <= to.Rooms &&
ro.MinSquareMeters <= to.SquareMeters &&
ro.MaxPrice >= to.Price &&
ro.MinFloors <= to.Floors &&
ro.TradeObjectId != to.TradeObjectId &&
ro.TradeObjectId != myTradeObject.TradeObjectId
select new RatingListTriangleModel
{
To1Id = myTradeObject.TradeObjectId,
To2Id = to.TradeObjectId,
To3Id = ro.TradeObjectId,
T1OnT2Rating = 0,
T2OnT3Rating = 0,
T3OnT1Rating = 0,
TotalRating = 0
};
foreach(var rlt in query)
this.InsertOrUpdate(rlt);
this.Save();
Related Topics
Non-Blocking Read from Standard I/O in C#
Why Aren't Generic Type Constraints Inheritable/Hierarchically Enforced
The Operation Cannot Be Completed Because the Dbcontext Has Been Disposed Using MVC 4
Adding Multiple Icons (Win32-Resource) to .Net-Application
Why Is Webbrowser_Documentcompleted() Firing Twice
Top Level Domain from Url in C#
How to Segment the Elements Iterated Over in a Foreach Loop
Dynamically Cross-Join Multiple Different-Size Collections Together in Linq (C#)
Linq: from a List of Type T, Retrieve Only Objects of a Certain Subclass S
Applying % Number Format to a Cell Value Using Openxml
Cannot Deserialize JSON Array into Type - JSON.Net
Datetime's Representation in Milliseconds
Cannot Deserialize the Current JSON Array (E.G. [1,2,3])