27
\$\begingroup\$

Since I don't know how LINQ works under the hood, I can't decide what version is best to use in term of rapidity of execution. I've done some testing with my testing data (Point Cloud) but I can't see a clear difference between the two. The only thing I know is that the real life data will be a larger Point Cloud so my guess is that the LINQ would be faster but this is only if LINQ doesn't do a for each under the hood. If it's the case, the 2 functions would be the same. What is your advice?

By the way, cylindre is a 3D cylinder and I want to know which point are inside.

Version 1 without LINQ

for (int i = 0; i < fpc.Vertices.Length; i++)
{
    if (cylindre.IsPointInside(fpc.Vertices[i]))
        listPoint.Add(fpc.Vertices[i]);
}

Version 2, with LINQ

var insidePoint =
    from pt1 in fpc.Vertices
    where cylindre.IsPointInside(pt1)
    select pt1;

    foreach (Point3D pt2 in insidePoint)
    {
        listPoint.Add(pt2);
    }
\$\endgroup\$
6
  • 5
    \$\begingroup\$ This might help: programmers.stackexchange.com/questions/80084/… \$\endgroup\$
    – ANeves
    Aug 1, 2012 at 12:44
  • \$\begingroup\$ @ANeves Interesting article. I don't think my question in premature since this is in the requirement and very important because it will be done like 500 times a day by each user. And the only reason I don't have real data is that the final product isn't ready but I know for sure that it will be larger so optimization at this moment is very important. I'm also considering other way of improving the function but the difference between linq and the foreach was something that interest me. \$\endgroup\$ Aug 1, 2012 at 13:06
  • 3
    \$\begingroup\$ Have you squeezed every bit of performance algorithmically? Which data structures and algorithms you use matters. Some highly optimized libraries for .Net will perform some computations faster. Also, perhaps it is possible to use PLINQ and utilize multiple cores at once? I would measure that too. \$\endgroup\$
    – Leonid
    Aug 1, 2012 at 15:49
  • \$\begingroup\$ Thanks for the info. In fact, we have created a very small subset to run the foreach now it runs super fast, with LINQ and the foreach. \$\endgroup\$ Aug 1, 2012 at 17:09
  • 1
    \$\begingroup\$ In the LINQ version, you might consider using AddRange() instead of foreach. It won't increase performance, but it will make your code more readable. Also, using Where() directly will be shorter than from/where/select. \$\endgroup\$
    – svick
    Aug 2, 2012 at 9:06

4 Answers 4

5
\$\begingroup\$

Under the hood LINQ will iterate over the collection, just as foreach will. The difference between LINQ and foreach is that LINQ will defer execution until the iteration begins.

Performance wise take a look at this blog post.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Just a note about that link. The link is dealing with deleting elements from a list. It uses a for loop, then contrasts that with a double foreach loop and a LINQ/foreach combo. Not really a fair comparison. \$\endgroup\$
    – pstrjds
    Aug 9, 2012 at 13:40
  • \$\begingroup\$ Also that link was three years old when this answer was posted, and is now over 11 years old. \$\endgroup\$
    – Yay295
    Aug 2, 2020 at 6:59
  • \$\begingroup\$ link is no longer valid \$\endgroup\$ Sep 17, 2020 at 15:34
  • \$\begingroup\$ Link is dead, please correct \$\endgroup\$
    – new2ios
    Jul 22, 2021 at 5:35
9
\$\begingroup\$

As has been said, the for loop will most likely be more performant, but you can still clean the code up a bit more:

for (int i = 0; i < fpc.Vertices.Length; i++)
{
    if (cylindre.IsPointInside(fpc.Vertices[i]))
        listPoint.Add(fpc.Vertices[i]);
}

Can become:

foreach (var vertice in fpc.Vertices)
{
    if (cylindre.IsPointInside(vertice))
        listPoint.Add(vertice);
}

EDIT: As per the performance question. This code will run in LINQPad. I found that the foreach version performs a few milliseconds better than the for loop.

var elements = Enumerable.Range(0, 4000000).Select(x => true).ToArray();


var sw = new Stopwatch();
var result = new List<bool>();
int trueCount = 0;
sw.Start();
for(int i=0; i < elements.Length; ++i)
{
    if (elements[i])
    {
        ++trueCount;
        result.Add(elements[i]);
    }
}

sw.Stop();
sw.ElapsedMilliseconds.Dump();

sw.Reset();
trueCount = 0;
result = new List<bool>();
sw.Start();
foreach(var element in elements)
{
    if (element)
    {
        ++trueCount;
        result.Add(element);
    }
}
sw.Stop();
sw.ElapsedMilliseconds.Dump();

EDIT2 - Regarding the link that seems to indicate such drastically poor performance in a foreach loop

The link (http://www.schnieds.com/2009/03/linq-vs-foreach-vs-for-loop-performance.html) is dealing with removing elements from a list. In the case that you have a generic list, removing elements via a for loop is not normally the best approach. A better approach is to use the RemoveAll method. RemoveAll will remove all elements matching the predicate and then consolidate the list as opposed to RemoveAt which will require moving all elements above the removed element. For performance comparison of the removal please see the below code (once again, this can be run in LINQPad). In my testing the RemoveAll ran roughly 250x faster.

var elements = Enumerable.Range(0, 100000).Select(x => x % 2 == 0).ToArray();

var sw = new Stopwatch();
var source = new List<bool>(elements);
sw.Start();
for(int i=0; i < source.Count; ++i)
{
    if (!source[i])
    {
        source.RemoveAt(i);
        --i;
    }
}

sw.Stop();
sw.ElapsedMilliseconds.Dump();
int count = source.Count;

sw.Reset();
source = new List<bool>(elements);

sw.Start();
source.RemoveAll((bool x) => {return x;});
sw.Stop();
sw.ElapsedMilliseconds.Dump();
\$\endgroup\$
3
  • \$\begingroup\$ Replacing the for loop by a foreach will decrease the performance, as stated in Xharze's link schnieds.com/2009/03/… \$\endgroup\$
    – Goldorak84
    Aug 9, 2012 at 13:09
  • 2
    \$\begingroup\$ @Goldorak84 - If you look at the code sample for that link, you will see that in both the foreach and LINQ case the code walked the list twice as compared to the for case that only walked the list once. That link was dealing with removing items from a list, and could have been written without a loop using RemoveAll which would be faster than even the for loop. \$\endgroup\$
    – pstrjds
    Aug 9, 2012 at 13:29
  • \$\begingroup\$ @pstrjds - I'm sorry, you are totally right. I adapted the code sample to apply the foreach and linq list removing mechanism on the for loop. The difference between the for and the foreach is barely noticeable. \$\endgroup\$
    – Goldorak84
    Aug 9, 2012 at 14:51
1
\$\begingroup\$

Update:

If you're targeting .net 4 or later, you could use:

Parallel.ForEach()

or

RemoveAll().Parallel();

They should be faster than other methods.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ List<T>.RemoveAll() returns an int representing the number of elements removed from the list. Did you mean List<T>.AsParallel()? \$\endgroup\$ Apr 15, 2014 at 22:13
0
\$\begingroup\$

I don't think it will run faster on LINQ. The function cylindre.IsPointInside would still have to be called on each item of Vertices.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.