Improve Performance with Static File Caching 

This post will be the first of what will be many posts with regards to application performance. After giving a number of presentations over the last 1-2 years, including one this evening in the Minneapolis/St. Paul area I've decided that some of these tips/tricks that I have with regards to improving application performance should really get put out here so people can find them and make the improvements to their applications. Going forward all of these posts will be categorized with at least the "Performance" category and then others that identify what systems are benefited by the changes. The subject of this post is Static Content Caching.

What is Static Content Caching and Why Do I Care?

Simply put what I am talking about here is an added piece of information that is sent along with the content of your web application that species the period of time that the user should be able to keep a copy of the file without requesting anything new from the server. In actual implementation what this means is when User A requests Picture1.jpg from your server not only do they get the file, but they get additional metadata within the response header that says, "Cache this until XX/XX /XXXX at yy:yyAM". With this information the browser can then elect to simply show the image from cache rather than re-requesting the image file every time you go to the page.

Why can this be helpful? Take into consideration a web application that has a graphics intensive design, potentially with multiple images in a rotator or similar function. Each time the page loads there are a number of assets that have to be downloaded. By default browsers will only make 4 requests to the same server at the same time, so if you have 16 elements that need to be loaded there are going to be at least 4 sets of trips to the server to get the results. If we put expiration durations on the files, we can avoid re-loading the content that doesn't change.

In this post I am going to talk specifically around the .NET configuration items for static content caching. This applies to any static piece of content that is NOT processed by the ASP.NET runtime. So items such as images, css files, js files, and the like with extensions that are NOT dynamically generated.

The Impact - Show Me The Data!

To provide a numerical example of exactly how drastic of an improvement this can have on page load, user perceived performance, and reduced server bandwidth I'll share some statics on a demonstration I gave this evening.

Looking at a web application homepage that does a default load with a number of images in content, skin, and content rotators using Fiddler we are able to see that the baseline configurations of the environment that a total of 52 web requests are needed to assemble the homepage and a total page size of 1.97Mb. Now, don't get me wrong, this page is WAY too heavy and that is a separate discussion for another post, but this met a clients need.

After adding the three lines to the web.config as outlined in the next section I tried to make a second request to the page. This time with the content refreshed the expiration headers all came down with the content. Upon a third load to the page I reviewed the results and a total of 3 web requests were needed for a total page size of 31 Kb. Now, 51 -> 3 and 1.97Mb -> 31 K is a huge difference for a simple web.config change.

Yes, the initial page load is still strong, but we are doing everything we can to ensure that the web server is only spending time serving the content that it needs to. We also make sure that we are not unnecessarily using bandwidth on the client side to request content that hasn't changed.

The Implementation

If you are running ASP.NET and running on IIS7, implementation is truly simple. Within the web.config of the application you would like to update, simply add the following within the <system.web%lt; node.

<staticContent>
<clientCache cacheControlMaxAge="7.00:00:00" cacheControlMode="UseMaxAge" />
</staticContent>

This sets the cache expiration time to 7 days for all static content. You can modify the value in the cacheControlMaxAge property as you see fit, the values are dd:hh:dd:ss so you can control with great precision how long it is cached.

As always feel free to share you successes, questions, or comments below! If you have an idea for a future performance post, please feel free to contact me.

Posted by Mitchel on Thursday, January 19, 2012
 

Comments

Will this work on IIS 7.5?

By Eoghano on Thursday, January 19, 2012 at 6:41 AM

I just tried this in my DNN 5.6.1 install (on a PowerDNN shared server, running IIS 7.5, ASP.net 4.0 and Windows NT 6.1 server) and I got a 500 - Internal server error. I placed a copy and paste of what you have above within the node as advised. Is there some element I am missing? Thanks for sharing this info it just what I was looking for as I prepare to launch a new site.

By Eoghano on Thursday, January 19, 2012 at 7:06 AM

I tried this on a 6.1.2 install of dnn, IIS 7.5 and I was getting the same error. If you check out this link http://www.iis.net/ConfigReference/system.webServer/staticContent/clientCache and follow the steps, you will see where the code is applied, its actually in the section of the web.config.

By James on Thursday, January 19, 2012 at 9:20 AM

Hello,

I also tried on my DNN 5.6.3 DNN on PowerDNN, same error than above...

Anything I am doing wrong as well ????

Thanks,
DV FX

By Declic Video on Thursday, January 19, 2012 at 3:08 PM

OK, I finally managed to get it working.

It needs to be in section and not into section.

But on my side, I do not see a lot of speed performance enhancement on my website. Try out this webpage for example, do you see a difference ??

http://declic-video-fx.com/language/en-US/Pinnacle-Studio/Tutorials.aspx

DV FX

By Declic Video on Thursday, January 19, 2012 at 3:12 PM

Mitchel, a timely article for something I'm working on. Does this mean caching of any .aspx pages, or are they all considered dynamic content and never cached?

By Bruce Chapman on Thursday, January 19, 2012 at 5:51 PM

By putting this into I got it to work. One thing I expected to see as a consequence was an improved YSLOW score. However my YSLOW scores did not change. What I see is that YSLOW is looking for 'expires' information in the HTTP header info of the static item however adding settings to the web.config injects a 'cache-control' value into the header. And YSLOW does not look for this. A search for the difference between 'cache-control' and 'expires' threw up the following stackoverflow page: http://stackoverflow.com/questions/5799906/whats-the-difference-between-expires-and-cache-control-headers

By Eoghano on Friday, January 20, 2012 at 2:51 AM

Good to know that this is the first performance tips of a bunch :). Regarding this article, I would love to know if there are any demerits related to user experience and freshness of the static contents. An example please. Thank you.

By Sangam Uprety on Friday, January 20, 2012 at 3:33 AM

You have implemented comment via a different page. Could this be your next article please? I hope, although this is strategic one, this is related to application performance and security.

By Sangam Uprety on Friday, January 20, 2012 at 3:35 AM

Name (required)

Email (required)

Website

CAPTCHA image
Enter the code shown above:

Content provided in this blog is provided "AS-IS" and the information should be used at your own discretion.  The thoughts and opinions expressed are the personal thoughts of Mitchel Sellers and do not reflect the opinions of his employer.

Friend of RedGate

www.datasprings.com - DotNetNuke ModulesICG

Click here for advertising information.

Content in this blog is copyright protected.  Re-publishing on other websites is allowed as long as proper credit and backlink to the article is provided.  Any other re-publishing or distribution of this content is prohibited without written permission from Mitchel Sellers.