Home Dashboard Directory Help
Search

LINQ: Enable caching of transformed expression trees in C# by Stefan Wenig


Status: 

Closed
 as External Help for as External


6
0
Sign in
to vote
Type: Suggestion
ID: 315491
Opened: 12/5/2007 8:17:57 AM
Access Restriction: Public
0
Workaround(s)
view

Description

When using LINQ to query SQL sources, the compiler-generated expression tree needs to be transformed to a SQL query. According to some reports, this transformation sometimes takes more time than executing the SQL query:
http://ayende.com/Blog/archive/2007/12/04/The-cost-of-inappropriate-linqing.aspx

There are two ways to resolve this problem:
a) improve the transforation performance
b) enable caching of the transformation result, so that the transformation only needs to be made once for each query

This suggestion shows a way to implement b)
Details
Sign in to post a comment.
Posted by Stefan Wenig on 2/28/2008 at 3:33 AM
Sorry for the delay, I got sick and then forgot about this.

Please be aware that I'm making a general observation here, so the question whether this work for me is not useful.

However, if anybody wants to know my opinion, I think compiled queries are just a hack and do little to solve the problem. LINQ is all about language integration, and the unparalleled ease of it. Doing queries is old, integrating it seamlessly into a static language is fantastic. Here's why compiled queries are just a hack, not a solution:
- The syntax for compiled queries kills the seamlessness of LINQ. Instead of just writing your query, you have to identify all parameters, put them into the lambda, write that awkward syntax. You might easily forget to include a parameter, but the query will still work - it will just use the value it got on the first execution. A pain to catch.
- You have to create singletons or use static variables to store those queries. With all the problems of lazy initialization, locking (memory model/volatile/double checked locking...) this can be hard and error-prone.
- For storing this query, you need either a) Func<A1,A2...R> etc, which is avaiable only up to 4 arguments, or b) a custom delegate type. If you want to use Func<> with more than 4 arguments, you'd need a custom parameter class, because anonymous types won't work here (need to declare members of this type).

This is all very odd. Now look at the SQL team and how much time they've spent at making queries fast and compiled, even if they're not stored as views or stored procedures. I'm quite sure that we need a similar mechanism for LINQ - one that silently caches queries and manages their disposal.

If you really think about it, it seems almost ridiculous that a static, compiled language like C# should perform so badly on each call. Due to the complicated ASTs that LINQ generates it might be worse than dynamic languages that do similar stuff but generate simple ASTs that match what the programmer wrote.

I really think that you need a good solution for this problem, as it will probably start to be a major performance killer in real-life LINQ apps. And nobody is going to like the answer, go profile your app, rewrite your major queries as compiled queries, and manage their caching.
Posted by Microsoft on 1/25/2008 at 4:42 PM
Stefan,

Have you had a chance to use a compiled query? This might get you the performance benefits you are looking for. Please report back to us when you have had the chance to try it out.

Thanks.
LINQ to SQL Team
Posted by Microsoft on 12/13/2007 at 2:35 PM
Stefan,

Thanks for reporting this issue. We will consider this bug for the next release of LINQ to SQL. Please keep sending the feedback as it helps us identify pressing issues that need addressing in the next release.

Thanks.
Faisal Mohamood
Program Manager | Microsoft
Sign in to post a workaround.