IIS7 Output Caching for Dynamic Content - Speed Up Your ASP and PHP Applications

Posted: May 02, 2007  4 comments  

Average Rating

Tags
Developers
IIS7
Performance

Share this Post

IIS7 has a new output cache feature that can cache dynamic content (output from your ASP.NET, Classic ASP, PHP or other dynamic pages) in memory.  This can yield enormous performance improvements since it means that the script used to generate that dynamic output doesn't need to run for each request.  The cache is "smart" enough to vary the output cached based on query string values as well as HTTP headers sent from the client to the server.  The cache is also integrated with the http.sys kernel mode driver, enabling blazing fast performance.

 

When to use it

IIS automatically caches static content (like HTML pages, images, and style sheets) for you, since these types of content don't change from request to request.  IIS also detects changes to the files when you make updates, and flushes the cache as needed.

The output from dynamic pages can now be cached in memory as well.  Not every dynamic page can take advantage of the output cache.  Pages that are highly personalized (like shopping cart / e-commerce transactions) are not good candidates because the dynamic output isn't likely to be requested again and again, and the memory used to cache the content would be wasted.  Content that is output as a result of a POST type request to an HTML form is also not cacheable.

Good candidates for the output cache are pages which are semi-dynamic in nature meaning the data is generated dynamically, but isn't likely to change from request to request based on the URL or the header information.  For example, photo gallery type applications that dynamically resize images for display in a web page are great candidates for the output cache because caching the data saves the server from having to re-process the image resizing for each request.  You can read more about this scenario, and how I used the output cache to get more than an order of magnitude greater performance with a PHP photo gallery application here.  Another good example of a type of application that can take advantage of the output cache feature is a stock ticker application.  Let's use it to walk through how such an application can take advantage of the output cache:

Varying the cache

Let's assume for this example that I have an application that allows the user to input a stock symbol which submits the symbol the my application as such:  http://server/showStockPrice.asp?symbol=MSFT

In this case, the URL is always http://server/showStockPrice.asp, but the querystring value (symbol=MSFT) tells the showStockPrice.asp page which data to include in the response, therby varying the output of the page by querystring value.  This is called varyByQuerystring in output cache lingo.  IIS also supports another type of cache policy: varybyHeaders which can vary the cache based on the HTTP headers that are sent from the client to the server.

Caching the output of this data is useful, because it is likely that many people may in fact by requesting the stock price for "hot" stocks ( like MSFT! :) ), and by caching it I save the server from having to lookup the current stock price for a particular symbol for each request. 

Invalidating the cache

Since we're caching dynamic data, there is a good chance it is going to change and we will need to flush the cache, allowing new data to be retrieved and re-cached.  In this example, the stock price is likely to change frequently.  Even in the case where the stock price is changing every second, it may be useful to cache the data if the site is getting hundreds of requests per second.  That could mean one trip to the database to retrieve the stock price, instead of a hundred every second, saving the Web server and the database server from extra work.

IIS supports two types of invalidation schemes for dynamic content.  The first is a simple timeout period.  The configuration property for this is CacheForTimePeriod.  The other way to invalidate the cache is for IIS to detect a change to the underlying resource.  The configuration property for this CacheUntilChange.  Use this type of invalidation scheme only when you want the cache flushed when the underlying resource (in this case showStockPrice.asp) changes. 

Configuring the cache

The cache is pretty easy to configure, and comes with a fancy UI feature in the new IIS admin tool to configure it (beta 3+ only). 

image

You can also configure the feature in your local web.config file that lives in the content directory.  Here is a sample of the configuration needed for our showStockPrice.asp page, with a varyByQueryString parameter of * (meaning cache all unique variations of querystring parameters) and a timeout of 1 second.

<configuration>
     <location path="showStockPrice.asp">
       <system.webserver>	
         <caching>
           <profiles>
             <add varybyquerystring="*"location="Any"
               duration="00:00:01" policy="CacheForTimePeriod"
               extension=".asp">
           </profiles>
	</caching>
       </system.webserver>
   </location>
</configuration>

If I want to cache this data in kernel for every faster performance, all I need to do is change the "policy" attribute to kernelCachePolicy.  Note: there are a few limitations you should be aware of with the kernel mode cache, read more about them below.

 

More Information

ThomaD recently published a more extensive article on output caching, located here:  http://learn.iis.net/page.aspx/154/iis-7-output-caching/  It will walk you through an end to end example of using the output cache, and provide troubleshooting tips and much more information on how to use this powerful new IIS7 feature.

Note: ASP.NET already has an 'output cache' feature that is very closely integrated with ASP.NET.  This IIS output cache feature works in parallel with that one, and works for all types of applications.

Comments

Really useful article! we've been doing a lot of investigation into caching performance internally so this info comes at a really good point ! Time to go install longhorn and test it with our sites ! :P

(Also I was trying to paste this to friends to read but the formatting seems to have freaked out slighly and some words are not visible on the right (IE7) - i read this originally via RSS)

May 03 2007 by Stephen Pope

Querystring values as well as headers? Interesting. That could be a great option for many dynamic pages, regardless of language. Others, however, obviously could vary their response by additional factors such as cookie values. Along the lines of caching, what would be interesting to see would be taking the concept of a dynamic 'page' and turning it into a dynamic ‘process’ that could be set to run and stay active until a sleep time is reached, but this process could have resources already loaded and ready, therefore potentially increasing response time. In other words a process that stays awake and listens for repeated requests and is ready to serve them, rather than several different threads or processes opening up, loading resources, processing a request and then quitting, only to restart again. I dare say it might be possible that in some rare cases the CPU cycles required to load the darn page are more than to process the actual request! Come to think of it, I might need to brush up on my ASP.NET, as it may already do that or something similar…

May 19 2007 by Will Smith