Chris Umbel

Linq to Object Performance

Linq (specifically Linq to object) really has improved the "feel" and readability of .Net code by turning what we used to do with flow control, like loops and conditionals, into a query expression.

Few people love tight code during development more than I, but I also have to support applications as they age. As the user base and application data grows performance almost always becomes a concern.

In that vein I figured I'd whip up a simple test over a sizable amount of data and compare the execution times of a Linq and a traditional approach to filtering a list.

First I needed something to build a list of:

public class Movie
{
	public string Title { get; set; }
        public TimeSpan RunTime { get; set; }
}

Then I filled a List named "movies" full of a nice round number of records... oh, say 1048576. 262143, roughly one quarter, of the records had a RunTime greater than 2 hours.

Now that I had some data it was time to test. The following is a Linq query I used to retrieve a list of movies longer than two hours and put them into a list named longMovies:

start = DateTime.Now;

List<Movie> longMovies = (from m in movies 
	where m.RunTime.Hours > 2
        select m).ToList();


Console.WriteLine(DateTime.Now.Subtract(start).Milliseconds);

Three executions resulted in an average of 204 milliseconds on an AMD Turion X2, 2.1 Ghz (updated on 2009/11/15 to more modern hardware).

Now to compare it to a traditional iterative approach:

start = DateTime.Now;

longMovies = new List<Movie>();

foreach (Movie m in movies)
{
	if (m.RunTime.Hours > 2)
        	longMovies.Add(m);
}

Console.WriteLine(DateTime.Now.Subtract(start).Milliseconds);

The average result after 3 executions: 132 milliseconds, about 2/3 of the Linq equivalent.

The moral of the story is that you have to be careful with Linq to object, at least with large sets. It may read nice and give you the "feel" of set-based operation, but under the hood the compiler's doing all sorts of expensive things like creating and calling delegates which it uses in Linq "Where" clauses. Your own conditionals will be far faster.

Mon May 11 2009 01:28:00 GMT+0000 (UTC)

Follow Chris
RSS Feed
Twitter
Facebook
CodePlex
github
LinkedIn
Google