Since ASP.NET 2.0 I’ve always liked the accessible way that caching has been presented to the ASP.NET developer. There are a number of good options for improving your server performance through server caches that are all really easy to get your head around and simple to implement in their most basic form.
Digging deeper into the cache
Like with most aspects of development when one looks more closely find it can get much more complex in order to optimise caching to your particular site heuristics.
The caching on the ecommerce site I’m working on at the moment was mostly removed during a site revamp last year, with the intention to put it back in again. Some of the new features I’m writing at the moment would be hit hard after a monthly email shot, thus caching is very attractive for these pages. Thus I ended up reminding myself of my options.
The site has a grid containing up to a thousand products and prices to show to the site visitor. The view of these items had to have the following features;
- Ability to sort the grid
- May filter the items viewed
- Can page the results with variable items per page
- Items in grid take context of current user language and currency selection
Page caching is not really helpful, instead I’m best caching the IEnumerable class that represents the items in the grid.
Watch out for bad performance behaviour
The thing you have to remember about web pages is that multiple users may be accessing the same page at the same time. This means you have to be a bit defensive about how you cache the object. I know the object take a long time to build as it comes from a database query that is quite intensive and some post query processing that takes a bit of time too, thus it is very realistic to see that if three users hit the page in quick succession when the cache is empty, they will all see it as empty and all simultaneously try to populate the cache, overwriting each other as they reach completion and write to the cache. Obviously this is going to load the application and database unnecessarily.
Reading around the subject I found the good old singleton pattern is a good one to start of using. If you’ve been through the joy of multithreaded applications you will know about Lock or SyncLock in vb. This allows you to lock a section of code so that only one thread may be running that section at any time. The other threads are blocked indefinitely waiting for the lock to clear. Well if you use a lock on the cache refresh, obviously the other users hitting the page will have to wait for the cache to be refreshed until they can move on and read from it.
The other one to watch out for out there that I noticed while reading up was many code examples for using the cache that forget that the item may drop out of the cache at any moment. So if you check the object exists in the cache, you need to grab it at the same time as next time you go to fetch it, it may have dropped out and nothing will be returned.
Got the cache working then used LINQ to Objects to get the paging and filtering working, what a joy to do, I’m really getting into LINQ!