RPM1984
RPM1984

Reputation: 73112

Strategies for "Pre-Warming" an ASP.NET Cache

I have an ASP.NET MVC 3 / .NET Web Application, which is heavily data-driven, mainly around the concept of "Locations" (New York, California, etc).

Anyway, we have some pretty busy database queries, which get cached after they are finished.

E.g:

public ICollection<Location> FindXForX(string x)
{
   var result = _cache.Get(x.ToKey()) as Locaiton; // try cache

   if (result == null) {
      result = _repo.Get(x.ToKey()); // call db
      _cache.Add(x.ToKey(), result); // add to cache
   }

   return result;
}

But i don't want to the unlucky first user to be waiting for this database call.

The database call can take anywhere from 40-60 seconds, well over the default timeout for an ASP.NET request.

I want to "pre-warm" these calls for certain "popular" locations (e.g New York, California) when my app starts up, or shortly after.

I don't want to simply do this in Global asax (Application_Start), because the app will take too long to start up. (i plan to pre-cache around 15 locations, so that's a few minutes of work).

Is there any way i can fire off this logic asynchronously? Maybe a service on the side is a better option?

The only other alternative i can think of is have an admin page which has buttons for these actions. So an administrator (e.g me) can fire off these queries once the app has started up. That would be the easiest solution.

Any advice?

Upvotes: 15

Views: 4326

Answers (8)

Khurrum
Khurrum

Reputation: 39

Sounds like you should just dump the results in a separate table and have a scheduled task to repopulate that table periodically.

If one pre-calculated table isn't enough because it ends up with too much data that you need to search through, you could use more than one.

Upvotes: 3

dove
dove

Reputation: 20674

Would suggest taking a look at auto-starting your app, especially if you are load balanced.

Upvotes: 1

Andrei R&#238;nea
Andrei R&#238;nea

Reputation: 20780

Look into "Always running" app setting for IIS 7.5. What this basically do is have an app pool ready whenever the existing one is to be recycled. Of course, the very first would take the 40-60 seconds but afterwards things would be fast unless you physically restart the machine.

Upvotes: 6

GavinH
GavinH

Reputation: 2213

Doing the loading in a Task from Application_Start is the way to go, as mentioned by Scott.

Just be careful - if your site restarts and 10 people try to view California, you don't want to end up with 10 instances of _repo.Get(x.ToKey()); // call db simultaneously trying to load the same data.

It might be a good idea to store a boolean value "IsPreloading" in the application state. Set it to true at the start of your preload function and false at the end. If the value is set, make sure you don't load any of your 15 preloaded locations in FindXForX.

Upvotes: 1

Mitch Wheat
Mitch Wheat

Reputation: 300549

Before you start cache warming, I suggest you check that the query is "as fast as it can be" by first looking at how many logical reads it is doing.

Upvotes: 3

Scott Weinstein
Scott Weinstein

Reputation: 19117

The quick and dirty way would be to fire-off a Task from Application_Start

But I've found that it's nice to wrap this functionality into a bit of infrastructure so that you can create an ~/Admin/CacheInfo page to let you monitor the progress, state, and exceptions that may be in the process of loading up the cache.

Upvotes: 6

Shan Plourde
Shan Plourde

Reputation: 8726

One option is to use a website health monitoring service. It can be used to both check website health, and if scheduled frequently enough, to invoke your common URLs.

Upvotes: 2

Maxim Zaslavsky
Maxim Zaslavsky

Reputation: 18065

One solution is to launch a worker thread in your Application_Start method that does the pre-warming in the background. If you do it right, your app won't take longer to start up, because the thread will be executed asynchronously.

Upvotes: 2

Related Questions