Response caching in IIS7

IIS caches everything it can to save CPU cycles wherever possible. IIS6 had user-mode file cache, token cache, URI cache, metadata cache and kernel-mode http.sys response cache. These caches are mostly unchanged in IIS 7.0 other than following changes I can think of.

  1. Static compression module disable kernel caching of response if static compression is enabled for the request but the client requested uncompressed response. This makes sure only compressed response is cached in kernel.
  2. You might see few changes in performance counters because URI cache module maintains additional pointers to cached files and metadata objects which saves some hashtable lookups.

Native output cache is the new user mode response cache added in IIS7. This module provides similar functionality as provided by the managed output cache module in ASP.NET. Functionality of this module can be controlled by editing system.webServer/caching section or by using IHttpCachePolicy intrinsic. Following properties can be set in system.webServer/caching section.

  1. enabled – This property tells if output caching is enabled or not for this URL. If disabled, output cache module won’t do anything in ResolveRequestCache and UpdateRequestCache stage. Setting enabled to true doesn’t ensure response caching. Some module must set user cache policy.
  2. enableKernelCache – Controls if kernel caching is enabled or not for this URL. Output cache module calls IHttpResponse::DisableKernelCache if this property is set to false. Output cache module does kernel caching work in SendResponse stage if no one called DisableKernelCache in the pipeline. Setting enableKernelCache to true doesn’t ensure kernel caching of response. Some module must set the kernel cache policy.
  3. maxCacheSize – Maximum size of output cache in MB. Value 0 means max cache size is calculated automatically. We use half of available physical memory or available virtual memory which ever is less.
  4. maxResponseSize – Maximum size of the response in bytes that can be stored in output cache. 0 means no limit.

Although you can set maxCacheSize, maxResponseSize for a URL, output cache module uses values set at root level only. If we have per apppool properties in future, these will be configurable for each application pool. If output cache is enabled, you can control its behavior for different file types by adding profiles for different file extensions. These profiles make output cache module populate IHttpCachePolicy intrinsic which enables user/kernel caching of response. Properties which can be set in a profile are similar to ones available for system.web/caching/outputCacheSettings profiles. Following properties are allowed for system.webServer/caching profiles:

  1. extension – E.g. “.asp”, “.htm” etc. * is used as wildcard entry. If profile for a particular extension is not found, profile for extension * will be used if present.
  2. policy – can be DontCache | CacheUntilChange | CacheForTimePeriod | DisableCache (only in server). Output cache module changes IHttpCachePolicy intrinsic depending on value of this property. DontCache means that intrinsic is not set but that doesn’t prevent other modules from setting it and enable caching. In server we have added DisableCache option which makes sure that response is not cached even if some other module sets the policy telling output cache module to cache the response.
  3. kernelCachePolicy – can be DontCache | CacheUntilChange | CacheForTimePeriod | DisableCache (only in server). As above, DontCache doesn’t prevent other modules from setting kernel cache policy. For static files, static file handler sets kernel cache policy which enable kernel caching of the response. In server DisableCache option makes sure that response doesn’t get cached in kernel.
  4. duration – duration property is only used when policy or kernelCachePolicy is set to CacheForTimePeriod.
  5. location – sets cache-control response header for client caching. Cache-control response header is set depending on value of this property as following.
    Any | Downstream – public
    ServerAndClient | Client – private
    None | Server – no-cache
  6. varyByHeaders – comma separated list of request headers. Multiple responses to requests having different values of these headers will be stored in the cache. You might be returning different responses based on Accept-Language or User-Agent or Accept-Encoding header. All the responses will get cached in memory.
  7. varyByQueryString – comma separated query string variables. Multiple responses get cached if query string variable values are different in different requests. In server you can set varyByQueryString to "*" (star) which makes output cache module to cache a separate response if any of the query string variable value is different.

varyBy and location headers are used by user mode cache only. These properties have no effect on kernel caching. So if policy is set to DontCache, these properties are not used. To make output cache module cache multiple responses by an asp page for 30 minutes which returns different responses based on value of querystring variable “action” and also based on request header “User-agent”, caching section will look like

<caching>
 <profiles enabled=”true”>
    <add extension=”.asp” policy=”CacheForTimePeriod” duration=”00:30:00” varyByQueryString=”action” varyByHeaders=”User-Agent”/>
 </profiles>
</caching> 

Output cache module populates the IHttpCachePolicy intrinsic in BeginRequest stage if a matching profile is found. Other modules can still change cache policy for the current request which might change user-mode or kernel mode caching behavior. Output cache caches 200 responses to GET requests only. If some module already flushed the response by the time request reaches UpdateRequestCache stage or if headers are suppressed, response is not cached in output cache module. Output cache module only caches the response if some other module hasn’t already cached it indicated by IHttpCachePolicy::SetIsCached. Also caching happens only for frequently hit content. Definition of frequently hit content is controlled by frequentHitThreshold and frequentHitTimePeriod properties defined in system.webServer/serverRuntime section. Default values define frequently hit content as ones which are requested twice in 10 seconds.
 

More details on IHttpCachePolicy coming in a future post.

-Kanwal

Leave a Reply

Your email address will not be published. Required fields are marked *