Reputation: 3482
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;
}
}
}
}
}
Upvotes: 9
Views: 22668
Reputation: 101681
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);
Upvotes: 18
Reputation: 43046
It is apparently significant that Sum has to store a boxed instance of the list enumerator on the heap, and use that heap object to iterate the list. The inline foreach and the for loop both avoid this; the former because List's public GetEnumerator method returns a value type. If you store a reference to people in an IEnumerable<Person>
variable, the foreach loop takes a little longer to get to its result.
Also, linq has to create objects for the where iterator and the delegate passed to it, and it does more null checks so it can throw informative exceptions if any of the arguments is null. That could account for the rest of the additional time required for the linq code.
Upvotes: 0
Reputation: 25116
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.
Upvotes: 1