Published: 25 Jul 2011
By: Matt Perdeck

Starting with this article, I'll show how to get the most out of the compression features built into IIS 7 and IIS 6. This first article focuses specifically on IIS 7.

Contents [hide]

The IIS compression Series

  • Part 1 Starting with this article, I'll show how to get the most out of the compression features built into IIS 7 and IIS 6. This first article focusses specifically on IIS 7.
  • Part 2 In this article, Matt Perdeck shows how to make the most out of IIS 6 compression.
  • Part 3 In this article, Matt Perdeck shows how to enable compression in your development environment, so you can keep track of how large your pages will be as they travel over the Internet to the browser.
  • Introduction

    Using compression is the single most effective way to reduce page load times. The .aspx files sent by the server to the browser consist of HTML. HTML is highly compressible by algorithms such as gzip. Because of this, modern web servers including IIS 5 and later have the ability to compress outgoing files, and modern browsers have the ability to decompress incoming files.

    You can find out at the following sites whether your pages already use compression, and if so, how much bandwidth you're saving:

    Both IIS 6 and IIS 7 offer advanced compression related options that help you get better performance improvements for your web site and make better use of your servers and bandwidth. Unfortunately, these options are not always easy to access. This article series shows step by step how to unlock these options.

    In this first article in the series, we'll focus on configuring compression in IIS 7. If you are used to IIS 6, you'll find that IIS 7 offers many new features, including the ability to cache not only compressed static files, but also compressed dynamic files. If you still use IIS 6, the next article in the series will show how to configure compression in IIS 6.

    Enabling compression in IIS 7 essentially consists of these steps:

    1. Installing the dynamic content compression module;
    2. Enabling Compression;
    3. Configuring advanced features.

    Lets go through these steps one by one.

    Installing the dynamic content compression module

    If you want to use compression for dynamic files, first install the dynamic content compression module. The steps to do this are different depending on whether you use Vista/Windows 7 or Windows Server 2008.

    On Windows Server 2008:

    Click Start | Administrative Tools | Server Manager.

    On the left-hand side, expand Roles and then click on Web Server (IIS).

    Scroll down to the Role Services section and then click on Add Role Services. The Add Role Services wizard opens:

    On the Select Role Services page, scroll down to the Performance section and select Dynamic Content Compression. Click on Next.

    Read the message and click Install.

    Once the installation is done, close the wizard.

    On Vista or Windows 7:

    1. Click on Start | Control Panel | Programs | Turn Windows features on or off. The Windows Features dialog opens.
    2. Expand Internet Information Services, expand World Wide Web Services, and expand Performance Features. Select Http Compression Dynamic.
    3. Click on OK. Wait for the feature to be configured.

    Enabling compression

    Now enable compression in the IIS manager:

    Open IIS manager. Click on Start Control Panel. Type admin in the search box. Click on Administrative Tools. Double-click on Internet Information Services (IIS) Manager.

    Click on your machine. Then double-click on the Compression icon on the right-hand side.

    The compression window opens. Here you can enable compression for dynamic content and static content. The window shows the following items:

    • Enable dynamic content compression: Unless your server already uses a lot of CPU, you will want to enable dynamic content compression.
    • Enable static content compression: You can safely enable static content compression because compressed static content gets cached. So, only the initial compression takes CPU cycles.
    • Only compress files larger than (in bytes): It makes sense to not compress small files. Because compression produces some overhead in the file, compressing a small file may actually make it bigger rather than smaller.
    • Cache directory: This is where compressed static files are stored. If you are short on disk space on the system drive, consider putting this on another drive. Make sure that the drive is a local drive or NTFS partition, and that it isn't compressed or shared.
    • Per application pool disk space limit (in MB): If you have lots of application pools and limited disk space, you may want to adjust this. If you have 100 application pools and you leave this at 100MB, 100 x 100MB = 10GB may be used to cache static compressed files.

    On the right-hand side of the window, click on Apply. Compression is now enabled.

    Setting compression by site, folder, or file

    In addition to enabling or disabling compression for all sites on the server, you can enable or disable compression at a site level, or even a folder or file level.

    To make this work:

    1. Open the IIS Manager and in the left-hand side click on the site, folder, or file whose compression status you want to change.
    2. Make sure that the middle pane is switched to Features View, and double-click on the Compression icon.
    3. This will open a window where you can enable or disable compression for dynamic or static files:

    Compression level

    You can tweak the tradeoff between compression and CPU usage by setting the compression level. The higher the compression level, the greater the compression and CPU usage.

    The compression level can be set separately for static and dynamic files. For static files, use 9, the highest level. For dynamic files, compression level 4 seems to be the sweet spot, as shown in this study.

    However, the optimal compression level for your website may be different, depending on how much spare CPU capacity you have, the compressibility of your pages, and your bandwidth costs. Experiment with different levels to see which one works best for you.

    To set the compression level:

    1. Execute this from the command prompt:

    (This sets compression level 9 for static files and compression level 4 for dynamic files).

    2. Reset the IIS server to make the new compression level take effect. In IIS Manager, click on the server at the top of the tree and then click on Restart on the right-hand side.

    Disabling compression based on CPU usage

    To make sure that compression doesn't overload the CPU, IIS 7 calculates average CPU usage every 30 seconds. It automatically switches off compression when CPU usage exceeds a given limit. Then when CPU usage drops below a second limit, it switches on compression again.

    The default values for these limits are:

    Table 1: Default values for CPU usage

     

    Switch compression off at(CPU usage)

    Switch back on at(CPU usage)

    Dynamic files

    90 percent

    50 percent

    Static files

    100 percent

    50 percent

    Note that this means that if CPU usage on your server is consistently over 50 percent, and when it spikes over 90 percent, compression for dynamic files will be switched off, but will never be switched back on again.

    You can change these limits by modifying the applicationHost.config file, which is normally in folder C:\Windows\System32\inetsrv\config:

    • Make a backup copy of applicationHost.config.
    • Open applicationHost.config with a text editor.
    • Find the <httpCompression> section.
    • To change the CPU usage at which compression for dynamic files is switched back on to 70 percent, add the dynamicCompressionEnableCpuUsage attribute to the httpCompression element, as shown:

    Note that you provide a number to the attribute, not a percentage, so don't write a percentage sign when setting the attribute. The value 70 shown here is simply an example, not a recommendation. You need to determine the optimal value for your own site.

    • Save the applicationHost.config file.
    • Reset the IIS server to make the new compression level take effect. Start IIS Manager, click on the server at the top of the tree, and then click on Restart on the right-hand side.

    In case you want to change any of the other limits, here are the matching attributes:

    Table 2: Attributes for changing the other limits

     

    Switch compression off at (CPU usage)

    Switch back on at (CPU usage)

    Dynamic files

    dynamicCompressionDisableCpuUsage

    dynamicCompressionEnableCpuUsage

    Static files

    staticCompressionDisableCpuUsage

    staticCompressionEnableCpuUsage

    If you want to stop IIS from ever switching off compression based on CPU usage, set all these attributes to 100.

    You will find all the elements and attributes that can be used with httpCompression here.

    Setting the request frequency threshold for static compression

    As you saw earlier, IIS 7 caches the compressed versions of static files. So, if a request arrives for a static file whose compressed version is already in the cache, it doesn't need to be compressed again.

    But what if there is no compressed version in the cache? Will IIS 7 then compress the file right away and put it in the cache? The answer is yes, but only if the file is being requested frequently. By not compressing files that are only requested infrequently, IIS 7 saves CPU usage and cache space.

    By default, a file is considered to be requested frequently if it is requested two or more times per 10 seconds. This is determined by two attributes in the serverRuntime Element in web.config:

    Table 3: The attributes in the serverRuntime element

    serverRuntime attribute

    Description

    frequentHitThreshold

    Number of times a URL must be requested within the time span specified in the frequentHitTimePeriod attribute to be considered frequently hit. Must be between 1 and 2147483647. Default is 2 .

    frequentHitTimePeriod

    Time interval in which a URL must be requested the number of times specified in the frequentHitThreshold attribute before it is considered to be frequently hit. Default is 10 seconds.

    This means that when a static file is requested for the very first time, it won't be compressed.

    For example, to specify that static files need to be hit seven times per 15 seconds before they will be compressed, use:

    Caching compressed dynamic files

    You've seen that IIS 7 caches only the compressed version of static files, and that dynamic files are compressed for each request (provided that dynamic file compression is enabled). This means that compressing dynamic files takes much more CPU than static files.

    That makes sense if the dynamic files are different for each visitor, for example if each page contains personal information. However, if the dynamic pages are fairly static and the same for all visitors, it makes sense to cache their compressed versions too.

    You may already use the ASP.NET OutputCache directive to cache your .aspx pages. The issue is that by default, IIS stores the uncompressed version of the file in the output cache, rather than the compressed version. For each request, IIS then has to compress the contents of the cache before sending it to the browser. This is not very efficient.

    Storing compressed files in the output cache

    Here is how to get IIS to cache the compressed version of the file, rather than the uncompressed version. That way, it doesn't have to compress the file for each request, reducing CPU usage.

    Because this uses ASP.NET output caching, you need to use the OutputCache directive in your pages, as shown:

    This caches the page for 300 seconds.

    Now to get IIS to cache the compressed version rather than the uncompressed version, modify the applicationHost.config file. You'll normally find this file in folder C:\Windows\System32\inetsrv\config:

    • Make a backup copy of applicationHost.config.
    • Open applicationHost.config  with a text editor.
    • Find the <urlCompression>  section.
    • Add the dynamicCompressionBeforeCache="true"  attribute to the urlCompression  element, as shown:
    • Save the applicationHost.config file.
    • Reset the IIS server to make the new attribute take effect.
    • Start IIS Manager, click the server at the top of the tree, and then click Restart on the right-hand side.

    What if a client doesn't accept compressed content?

    Now that we're caching compressed content, what happens if someone visits your site with a browser that doesn't accept compressed content?

    To simulate this eventuality, let's send a request to the server that doesn't have the Accept-Encoding request header. This should force the server to send uncompressed content. I'll discuss the request and response headers involved in compression in part 4 of this series.

    To do this, we'll use Fiddler, a free proxy which allows you to "fiddle" with requests and responses while they are travelling between browser and server. It's easiest to do this with Firefox:

    • Open Firefox and download Fiddler at http://www.fiddler2.com/fiddler2/
    • Install Fiddler and start it.
    • On the Firefox status bar, switch on forcing traffic to Fiddler.

    • At this stage, when you visit a page with Firefox, the server should still use compression (assuming the request has an Accept-Encoding  request header allowing gzip compression).

    You can measure the actual size of your compressed pages as they will travel over the Internet to the browser, using the Web Developer add on for Firefox or Google Chrome. Here is how to use it with Firefox:

    • Using Firefox, visit http://chrispederick.com/work/web-developer to download and install the Web Developer add on.
    • After you have installed Web Developer, load the page again.
    • Right click anywhere in the page. A popup menu will appear. Click Web Developer | Information | View Document Size. A new window appears showing the groups of files making up the page.
    • Expand the Documents group to see the size of the page. If it was compressed while travelling over the Internet, you will also see its compressed size.
    • Now get Fiddler to strip off the Accept-Encoding request header from the request going from Firefox to the web server. In the Fiddler window on the right-hand side, click on the Filters tab, select Use Filters, select Delete request header, and type in Accept-Encoding.

    • Refresh the page in Firefox. Check the file size again with Web Developer. You should find that no compression was used with this request. That will make browsers that do not support compression happy. So far, so good.
    • In Fiddler, uncheck the Delete request header checkbox. As a result, the Accept-Encoding request header now makes it to the web server again.
    • Refresh the page. The server should now compress the file again. But if you check with Web Developer, you'll find that it is still sending files uncompressed!
    • This is because when IIS received the request for uncompressed content, it threw away the compressed contents in the cache, regenerated the content and stored it uncompressed in the cache. It then keeps serving this uncompressed content until the cache expires, even to clients that accept compressed content.
    • You can prevent this from happening by caching both compressed and uncompressed content. You do that by including VaryByContentEncoding in the OutputCache directive, as shown in the following code:
    • If you now delete the Accept-Encoding header and then let it go through again, you'll see that the server always sends compressed content to clients that accept it, even if another client didn't accept it.
    • Before you end this experiment and close Fiddler, go back to the Firefox status bar and stop sending traffic to Fiddler. Otherwise Firefox will complain about the missing proxy when you close Fiddler.

    A drawback of using VaryByContentEncoding in the OutputCache  directive is that it disables kernel caching for this file. Kernel caching is a highly efficient form of server side caching, and is discussed in Chapter 5 of my book ASP.NET Site Performance Secrets.

    So should you use VaryByContentEncoding  in the OutputCache  directive? Seeing that you are reading this chapter, the gain in compression by using VaryByContentEncoding  may well outweigh the loss of kernel caching, especially seeing that you already use output caching. Your best bet would be to try both scenarios in production for a while, and compare CPU usage, response times, and bandwidth used per request for each scenario.

    Summary

    In this article, we saw how to configure compression on IIS 7, including its more advanced, lesser known features. In the next article, I'll show how to get the most out of the compression features built into IIS 6.

    If you enjoy this series and want to know the full story on how to improve ASP.NET site performance, from database server to web server to browser, consider my book ASP.NET Site Performance Secrets. Or visit my web site ASP.NET Performance.

    The IIS compression Series

  • Part 1 Starting with this article, I'll show how to get the most out of the compression features built into IIS 7 and IIS 6. This first article focusses specifically on IIS 7.
  • Part 2 In this article, Matt Perdeck shows how to make the most out of IIS 6 compression.
  • Part 3 In this article, Matt Perdeck shows how to enable compression in your development environment, so you can keep track of how large your pages will be as they travel over the Internet to the browser.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Matt Perdeck

    Matt has over 6 years .NET and SQL Server development experience. Before getting into .Net, he worked on a number of systems, ranging from the largest ATM network in The Netherlands to embedded software in advanced Wide Area Networks. He has lived and worked in Australia, The Netherlands, Slovakia a...

    This author has published 4 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    IIS FTP User Isolation - Week 46
    This week we walk through the five isolation modes to gain a full understanding of the IIS FTP metho...
    FTP Firewall settings, Active vs. Passive, and FTPS Explicit vs. Implicit Week 47
    Understanding Active and Passive mode for FTP is useful for troubleshooting and ensuring that the fi...
    Q&A. DNS Load Balancing, Google and Geo-location, CDNs-Week 50
    This week answers two Q&A questions from viewers. DNS Load Balancing and then some discussion and a ...
    Q&A. What’s new in IIS8, Perf, Indexing Service–Week 49
    This week I'm taking Q&A from viewers, starting with what's new in IIS8, a question on enable32BitAp...
    IIS FTP Troubleshooting - Week 48
    This lesson covers ways to troubleshoot IIS FTP. When it works, it works well, but if you run into i...

    You might also be interested in the following related blog posts


    Web Deployment Tool released to web (RTW) read more
    Don’t use Response.End() with OutputCache read more
    Kobe - Oh Dear Lord Why?! read more
    Trip Report from Gov 2.0 Camp read more
    IIS 7 Compression. Good? Bad? How much? read more
    "Software is everything. (It also sucks.)" - What does this have to do with DotNetNuke? read more
    URL Rewrite for IIS - SEO Friendly URLs love it ! read more
    Silverlight Controls read more
    ASP.NET tab in IIS, more dangerous than it first appears! read more
    WCF REST Configuration for ASP.NET AJAX and plain REST Services read more
    Top
     
     
     

    Please login to rate or to leave a comment.