Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ vs foreach vs for performance test results

Could somebody explain these results? I know there are duplicate questions, but I have yet to find a single question that came to the same conclusion as my results :o

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SpeedTest
{
    class Person
    {    
        public Person(string name)
        {
            this.Name = name;
        }

        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var people = new List<Person>();
            AddTwins("FRANCISCO", people);
            var stopwatch = new Stopwatch();

            string name = "OCSICNARF";

            long linqTime = 0L;
            long foreachTime = 0L;
            long forTime = 0L;

            stopwatch.Start();
            Person person0;
            var result = from person in people
                         where person.Name == name
                         select person;
            person0 = result.First();
            linqTime = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();
            Person person1;
            foreach (Person p in people)
            {
                if (p.Name == name)
                {
                    person1 = p;
                    break;
                }
            }
            foreachTime = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();
            Person person2;
            for (int i = 0; i < people.Count; i++)
            {
                if (people[i].Name == name)
                {
                    person2 = people[i];
                    break;
                }
            }
            forTime = stopwatch.ElapsedMilliseconds;
            stopwatch.Stop();

            Console.WriteLine(string.Format("LINQ took {0}ms", linqTime));
            Console.WriteLine(string.Format("FOREACH took {0}ms", foreachTime));
            Console.WriteLine(string.Format("FOR took {0}ms", forTime));
        }

        static void AddTwins(string name, List<Person> people)
        {
            AddTwins(people, name, "");
        }

        private static void AddTwins(List<Person> people, string choices, string chosen)
        {
            if (choices.Length == 0)
            {
                people.Add(new Person(chosen));
            }
            else
            {
                for (int i = 0; i < choices.Length; i++)
                {
                    // choose
                    char c = choices[i];
                    string choose1 = choices.Substring(0, i);
                    string choose2 = choices.Substring(i + 1);
                    choices = choose1 + choose2;

                    // explore
                    AddTwins(people, choices, chosen + c);

                    // Unchoose
                    string unchoose1 = choices.Substring(0, i);
                    string unchoose2 = choices.Substring(i);
                    choices = unchoose1 + c + unchoose2;
                }
            }
        }
    }
}

enter image description here

like image 913
Francisco Aguilera Avatar asked Apr 04 '14 00:04

Francisco Aguilera


2 Answers

You never execute the LINQ query, you just create it. You should use ToList or ToArray method to force an iteration, probably you won't get a different result because LINQ uses a foreach loop as well.

Edit: LINQ takes a little bit more time because you are iterating over all of the items. But in your other two loops you are breaking the loop as soon as you find a match. Try using FirstOrDefault instead of Where and you should get the same (or similar) result.

people.FirstOrDefault(p => p.Name == name);
like image 108
Selman Genç Avatar answered Oct 22 '22 00:10

Selman Genç


the linq one is taking no time because the query is never actually evaluated.

Linq is lazy for most operations, it won't actually do anything until someone starts enumerating the results.

if you added

result.Count(); // add this line, query will be evaluated
linqTime = stopwatch.ElapsedMilliseconds;
stopwatch.Restart();

then i'm pretty sure you'd have a non-zero result for linq.

like image 32
John Gardner Avatar answered Oct 22 '22 01:10

John Gardner