1

I'm experiencing performance issues on some of my queries against EF5 DbContext model in my ASP MVC application.

The queries have many includes over multiple levels of navigation graph, e.g.:

Context.Cars
.Include(c=>c.Model.Maker)
.Include(c=>c.CarOwners.Select(co=>co.Owner))
.Include(c=>c.Navigation1)
.Include(c=>c.Navigation2)
.Include(c=>c.Navigation3)
.ToList();

The first time I run a query it takes about 10 seconds to execute, but when I refresh the page the second time it takes less then a second to execute.

I have run Visual Studio's Performance Analysis tool to see where is the problem and it seems that the GetExecutionPlan() method is consuming most of the time.

I guess the plan is being cached since the second time the query is run (on a page refresh) the query is executed really fast (less then a second).

I understand that the performance of fistp page load is limited since the query is really complicated (the SQL code dumped to DB is about 4k lines long). But the problem is that if I return to the page in an hour or so the query is slow again. It seems like the execution plan cache is cleared somehow? I've checked IIS settings and all application pool recycling setting are turned off.

Just to be clear, I'm not looking for methods to optimize my queries, I'm wondering why my query behaves strangely: first load slow, second load fast and load after one hour again slow.

Any ideas?

4

1 回答 1

1

(dotPeek to the rescue. I couldn't find the class in the source on Codeplex, it may have been removed in v6.)

There's an internal class System.Data.Common.QueryCache.QueryCacheManager in EntityFramework.dll v5.0.0.0, which does what it says, but is a bit complex.

Here's what I'm pretty sure about: There is a timer which is started (if not already running) when a plan is added to the cache. The timer triggers a sweep of the cache every 60000 milliseconds (1 minute), and the cache is then actually swept if there are more than 800 plans cached. Plans which have not been re-used since the last sweep are evicted from the cache. If the cache has fewer than 800 plans in it, the sweep is skipped and the timer is stopped.

Here's what I'm not so sure about: There's part of the cache sweep I don't quite understand, but I assume it's clever. It looks like the algorithm makes it harder for a plan to stay in the cache the more sweeps it lives through, by bitwise shifting its hit count rightward by increasing amounts each sweep. On the first and second sweep it gets shifted 1, then 2, then 4, up to 16. I'm not sure what the reason for this is, and I'm having a hard time figuring out exactly how many times a plan needs to be used for it to stay in the cache more than 5 minutes. I'd appreciate it if anyone could give more information about 1) exactly what it's doing, and 2) what the rationale might be for doing this.

Anyway, that's why your plan isn't being cached forever.

于 2013-08-20T00:03:42.080 回答