Entity Framework & WCF Data Services June 2011 CTP : Auto Compiled LINQ Queries

Ahh another one of the very awesome features of the new CTP!

Pre-compiled LINQ to Entities queries (LINQ to SQL has them too) are an incredible performance boost. Entity Framework has to a bit of work to read your LINQ to Entities query, then scour through the metadata to figure out what tables & columns are involved, then pass all of that info to the provider (e.g., System.Data.SqlClient) to get a properly constructed store query. If you have queries that you use frequently, even if they have parameters, it is a big benefit to do this once and then reuse the store query.

I’ve written about this a lot. It’s a bit of  a PIA to do especially once you start adding repositories or other abstractions into your application. And the worst part is that they are tied to ObjectContext and you cannot even trick a DbContext into leveraging CompiledQuery. (Believe me I tried and I know the team tried too.)

So, they’ve come up with a whole new way to pre-compile and invoke these queries and the best part is that it all happens under the covers by default. Yahoo!

Plus you can easily turn the feature off (and back on) as needed. With CompiledQuery in .NET 3.5 & .NET 4.0, the cost of compiling a pre-compiling a query that can be invoked later is more expensive than the one time cost of the effort to transform a L2E query into a store query. Auto-Compiled queries work very differently so I don’t know if you need to have the same concern about turning it off for single-use queries. My educated guess is that it’s the same. EF still has to work out the query,then it has to cache it then it has to look for it in the cache. So if won’t benefit from having the store query cached, then why pay the cost of storing and reading from the cache?

I highly recommend reading the EF team’s walk-through on the Auto-Compiled Queries for information on performance and more details about this feature and how it works. Especially the note that this paper says CompiledQuery is still faster.

A bit of testing

I did a small test where I ran a simple query 10 times using the default (compiled) and 10 times where I’ve turned off the compilation. I also started with a set up warmup queries to make sure that none of the queries I was timing would be impacted by EF application startup costs. Here you can see the key parts of my test. Note that I’m using ObjectContext here and that’s where the ContextOptions property lives (same options where you find LazyLoadingEnabled, etc). You can get there from an EF 4.1 DbContext by casting back to an ObjectContext.

 

  public static void CompiledQueries()
    {
      using (var context = new BAEntities())
      {
        FilteredQuery(context, 3).FirstOrDefault();
        FilteredQuery(context, 100).FirstOrDefault();
        FilteredQuery(context, 113).FirstOrDefault();
        FilteredQuery(context, 196).FirstOrDefault();
      }
    }
    public static void NonCompiledQueries()
    {
      using (var context = new BAEntities())
      {
        context.ContextOptions.DefaultQueryPlanCachingSetting = false;
        FilteredQuery(context, 3).FirstOrDefault();
        FilteredQuery(context, 100).FirstOrDefault();
        FilteredQuery(context, 113).FirstOrDefault();
        FilteredQuery(context, 196).FirstOrDefault();
      }
    }

    internal static IQueryable<Contact> FilteredQuery(BAEntities context, int id)
    {
      var query= from c in context.Contacts.Include("Addresses") where c.ContactID == id select c;
      return query;
    }

I used Visual Studio’s profiling tools to get the time taken for running the compiled queries and for running the queries with the compilation set off.

When I executed each method (CompiledQueries and NonCompiledQueries) 3 times, I found that the total time for the compiled queries ran about 5 times faster than the total time for the non-compiled queries.

When I executed each method 10 times, the compiled queries total time was about 3 times faster than the non-compiled.

Note that these are not benchmark numbers to be used, but just a general idea of the performance savings. The performance gain from using the pre-compiling queries is not news – although again, auto-compiled queries are not as fast as invoking a CompiledQuery. What’s news is that you now get the performance savings for free. Many developers aren’t even aware of the compiled queries. Some are daunted by the code that it takes to create them. And some scenarios are just too hard or in the case of DbContext, impossible, to leverage them.

WCF Data Services

I mentioned data services in the blog post title. Because this compilation is the default, that means that when you build WCF Data Services on top of an Entity Framework model, the services will also automatically get the performance savings as well.

Enjoy!

  Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!  

6 thoughts on “Entity Framework & WCF Data Services June 2011 CTP : Auto Compiled LINQ Queries

  1. Julie, I don’t think relative numbers (like "3 times faster") are appropriate here. As expression tree converting to storage query takes fixed time the difference between absolute numbers would mean more, in my opinion (in this we can exclude query execution, data retrieval, etc. time).

    And it would be interesting to see the third option – good old CompiledQuery and to see how much does it take to calculate expression tree hash.

  2. Hi Alexander,

    I have done quite a lot of blog posts, conference presentations, articles and even sections of my books where I’ve done comparative perf tests on EF and shown the numbers. My interest here was solely to see how the auto-compiled queries compare to the regular queries which is why rather than use hard numbers, I’m generalizing. I’d certainly be interested in seeing any comparitive #s you find if you are doing any of the research yourself.

  3. Julie,

    I just read the ado.net blog on table value functions(entity framework) that can be used for silverlight and wcf ria, code first etc. Do you have any plans to write a new updated book on this subject?

    1. Hi Javi,
      The auto compiled queries are cached for the lifetime of the application. There is a caching algorithm and eventually they will get flushed out, but otherwise, they should be getting reused automatically.

      The compiledquery doesn’t work with DbContext. Some devs made workarounds, but once the auto compiled queries came out, which are so much easier to benefit from (effortless) and work with DbContext, there is little reason to use compiledquery anymore.

      Julie

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.