Changes to compression in IIS7

Posted: Jun 13, 2006  21 comments

Average Rating

Tags

Compression module provides IIS the capability to serve compressed responses to compression enabled clients. Clients which can accept compressed responses send Accept-Encoding header indicating compression schemes they can handle. If IIS can compress the response using a compression scheme which client can understand, IIS will send a compressed response with Content-Encoding response header indicating the scheme which was used to compress the response.

So request response look something like

REQUEST: **************
GET /static/index.htm HTTP/1.1\r\n
Accept-Encoding: gzip, deflate\r\n
Host: localhost\r\n
Accept: */*\r\n
\r\n
RESPONSE: **************
HTTP/1.1 200 OK\r\n
Content-Type: text/html\r\n
Content-Encoding: gzip\r\n
Last-Modified: Tue, 28 Mar 2006 03:44:06 GMT\r\n
Accept-Ranges: bytes\r\n
ETag: "087e0dc1952c61:0"\r\n
Vary: Accept-Encoding\r\n
Server: Microsoft-IIS/7.0\r\n
X-Powered-By: ASP.NET\r\n
Date: Tue, 13 Jun 2006 02:23:41 GMT\r\n
Content-Length: 438\r\n

This is useful to save network bandwidth and offer clients faster download times. This was first added in IIS6 and could be enabled for static/dynamic content individually. Following set of changes are made to compression modules in IIS7:

  1. Static compression is ON by default in IIS7. Dynamic compression is still OFF by default which can be turned ON for all content by running
    appcmd set config -section:urlCompression /doDynamicCompression:true
  2. In IIS6, static compression was happening on a separate thread. So on receiving a request, first response was uncompressed and IIS used to start a separate thread to compress the file and keep it in compressed files cache. Requests for compressed content reaching IIS after the compression is complete used to receive compressed response. In IIS7, compression happens on the main thread. But to not incur cost of compression for all requests compression happens only for frequently requested content. Definition of frequently requested content is controlled by properties frequentHitThreshold and frequentHitTimePeriod under section system.webServer/serverRuntime. If IIS receives more than threshhold number of requests in frequentlyHitTimePeriod for the same url, IIS will go ahead and compress the file to serve compressed response for the same request which made IIS reach threshhold. This compressed response is saved in the compressed files cache as in IIS6. If compressed response was already present in compression cache, frequentHitThreshhold logic is not applied as compresed content will be picked from cache and there will be no additional cost for compressing the content. Hit count is maintained per URL. So sending first request with Accept-Encoding: gzip and second with deflate will still qualify as frequentlyHit content and IIS will go ahead and compress the response. This will require cachuri.dll to present in the globalModules section as that is the module which keeps URL hit count (More about globalModules someday later).
  3. Temporary compressed files folder has a nested directory structure in IIS7 compared to a flat one in IIS6. We create folder for each apppool in temporary compressed files and then create separate folders for different schemes under each apppool. Under these scheme folders, we create folder structure similar to folder from where the content was picked. So if iisstart.htm from D:\inetpub\wwwroot got compressed using gzip, cache entry will get created in
    D:\inetpub\temp\IIS Temporary Compressed Files\DefaultAppPool\$^_gzip_D^\INETPUB\WWWROOT folder. We ACL the apppool folder with worker process identity to protect the content from worker processes serving some other apppools. Directory is still configurable from config but the default is moved from %windir%\iis temporary compressed files to %SystemDrive%\inetpub\temp\iis temporary compressed files. Also with this change, maxDiskSpaceUsage limit is applied per apppool. So if you had a value of 100MB for HcMaxDiskSpaceUsage in IIS6, that limit was applied to all the compressed content in the compressed files cache. Now this limit applies to compressed files per apppool. If you have 10 apppools and have maxDiskSpaceUsage set to 100MB, total space allocated to compressed files cache is actually 1GB.
  4. As static compression is enabled by default and compression is happening on the main thread, we added on the fly compression shutoff/resume depending on CPU load. Four properties are added to system.webServer/httpCompression section to control this behavior. These are
    - staticCompressionDisableCpuUsage - compression is disabled when average CPU usage over a time period is above this number.
    - staticCompressionEnableCpuUsage - compression is enabled back if average CPU usage over a time period falls below this number.
    - dynamicCompressionDisableCpuUsage and dynamicCompressionEnableCpuUsage enables or disables dynamic compression depending on load of CPU.
    We calculate average CPU utilization every 30 sec.
  5. In IIS7, you can enable/disable compression depending on the content-type of response. In IIS6 this was possible on extension basis which is no longer possible. Now you can have just one entry in the config to enable static or dynamic compression for text/html responses. You no longer need to pick up all extensions which return text/html responses. While configuring these mimeTypes under httpCompression section, you can use * as wildcard. If response type is text/html, we look for an entry for text/html and if found use the corresponding enabled value. If text/html is not found, we look for text/* or */html. If both are present we pick the one which comes first and use that enabled property value. If these are also not found, we look for */* and use the corresponding enabled value. For enabling compression for all content types, add an entry under httpCompression section in applicationHost.config which says
        <staticTypes>
            <add mimeType="*/*" enabled="true" />
        </staticTypes>
  6. Bunch of IIS6 compression properties are removed in IIS7. These are
    - HcMaxQueueLength. As compression is happening on main thread, queue length property is not used anymore and is removed.
    - HcCreateFlags property which was used to pass a value to gzip.dll (indicating gzip or deflate compression) is removed as it was not useful for the customers.
    - HcFileExtensions and HcScriptFileExtensions are removed as we no longer enable/disable compression based on extension.
    - HcIoBufferSize and HcCompressionBufferSize properties are removed as we believe those are not useful for customers.
    - HcDoOnDemandCompression is removed. For enabling static compression, only doStaticCompression property is required to be set.
    - HcFilesDeletedPerDiskFree is no longer there in IIS7. We just delete as many files as required to get to 90% of the maxDiskSpaceUsage. We pick least recently used files to delete.
    - HcPriority is removed as scheme to use when multiple ones appear in Accept-Encoding header of request is picked depending on scheme which is appear first in Accept-Encoding header (assuming no q factor). This is as per HTTP specs.

    I think ability to add new schemes in config is not very useful. I have not seen any compression scheme implementation outside Microsoft which can be used with IIS. If you want to implement your own scheme, you need to write a dll with following exports
    - Compress
    - CreateCompression
    - DeInitCompression
    - DestroyCompression
    - InitCompression
    - ResetCompression
    If you want signatures of these functions, write to me and i can take your case to the management. Most probably you will get the signatures very easily.
  7. maxDiskSpaceUsage entry is changed to be configured in MB rather than bytes. We realized that people don't really want to configure the limit to the byte level but the main reason was we have the limit as UINT and we didn't want customers to set it to a value which cannot be stored in UINT. With large disks today, having a large value won't be uncommon.
  8. With static compression enabled by default, now we only cache compressed responses in the kernel (HTTP.Sys). So if compression is enabled for a file but the current request didn't contain Accept-Encoding header (or compression didn't happen because it was the first request), we don't tell http.sys to cache it. Only compressed response is cached in the kernel for which compression is enabled. Dynamically compressed responses are not cached in any of the caches (even in compressed files as was in IIS6).
  9. Deflate is removed in default configuration but the functionality is still present in gzip.dll. To add deflate scheme, add the following in httpCompression section:
        <scheme name="deflate" dll="%Windir%\system32\inetsrv\gzip.dll" />
    You can use following appcmd command.
    appcmd set config /section:httpCompression /+[name='deflate',dll='%Windir%\system32\inetsrv\gzip.dll']
  10. As static compression is enabled by default, default value of staticCompressionLevel is changed from 10 to 7.

Most of the compression properties (present under system.webServer/httpCompression) can be set in applicationHost.config for the server and cannot be configured on URL basis. We might have per apppool properties someday and if we end up doing per apppool properties, properties under httpCompression will be configurable per apppool. doStaticCompression and doDynamicCompression boolean properties under system.webServer/urlCompression section can be set at URL level which can be used to enable/disable compression per URL. This is similar to what was in IIS6.

I think i have mentioned all the changes that are coming in IIS7 as far as compression is concerned. If i realize that i missed something, i will do another post.

-Kanwal

Comments

  1. Chintan Parmar
    June 20, 2007

    Hello,

    This is nice to know, for IIS7 about the compression. But I have one question for this, if you could provide me an answer that would be greate, and I really appriciate that.

    i tried to use http compresion on IIS7, but somehow, i guess that dose not give me any result.

    I tried to access my website using the folllwing webtools.

    www.port80software.com/.../compresscheck.asp

    which always shows me, Compression Status : notcompress [:(]

    So, i guess something more we need to do httpCompression in IIS7.

    Please look into the following what i wrote in my web.config file.

    <system.webServer>

    <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">

    <dynamicTypes>

                   <add mimeType="text/*" enabled="true" />

                   <add mimeType="message/*" enabled="true" />

                   <add mimeType="application/x-javascript" enabled="true" />

                   <add mimeType="*/*" enabled="true" />

               </dynamicTypes>

               <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />

    </httpCompression>

           <modules>

               <add name="URLRewriter" type="ILink.Beonit.HTTPModules.URLRewriter, ILink.Beonit.HttpModules.URLRewriter" preCondition="managedHandler" />

               <add name="Authentication" type="ILink.Beonit.HTTPModules.Authentication, ILink.Beonit.HttpModules.Authentication" preCondition="managedHandler" />

               <add name="ModuleRewriter" type="ILink.Beonit.HTTPModules.ModuleRewriter,ILink.Beonit.HTTPModules.URLRewriter" preCondition="managedHandler" />

               <add name="ImageServer" type="ILink.Beonit.HTTPModules.ImageServer, ILink.Beonit.HttpModules.ImageServer" preCondition="managedHandler" />

           </modules>

           <handlers>

               <add name="ajax/*.ashx_POST,GET" path="ajax/*.ashx" verb="POST,GET" type="Ajax.PageHandlerFactory, Ajax" preCondition="integratedMode,runtimeVersionv2.0" />

           </handlers>

           <validation validateIntegratedModeConfiguration="false" />

           <httpRedirect enabled="false" destination="http://www.beonit.net" />

           <urlCompression doDynamicCompression="true">

    </urlCompression>

       </system.webServer>

    I am awaiting for your reply

  2. ksingla
    June 24, 2007

    Chintan,

    Are you sure you wrote httpCompression section properties in web.config? HttpCompression section is defined AppHostOnly in applicationHost.config which prevents you from setting its properties in web.config. Compression module only reads server level properties from applicationHost.config. If you allowed httpCompression section by modifying section definition in applicationHost.config, that might be a problem. See if this is the problem.

    Kanwal

  3. Vlad
    August 2, 2007

    When you say "the main thread", do you mean a request thread, or the main IIS service thread?

    One compression thread per app pool, or many?

  4. ksingla
    August 2, 2007

    Vlad,

    By main thread, I meant request thread. There is no dedicated thread to do compression in IIS7 and so there can be many threads in a worker process doing compression.

    Kanwal

  5. Vlad
    August 3, 2007

    Thank you very much for the information, it is very helpful to understand how much it has changed from IIS 6.0!

  6. mike
    November 9, 2007

    Javascript won't work on a webpage in iis7 ?

  7. spenser
    November 11, 2007

    I think that removing the various knobs is a mistake. Setting a good default value and leaving the knobs available would be my preference.

    As for:

    HcPriority is removed as scheme to use when multiple ones appear in Accept-Encoding header of request is picked depending on scheme which is appear first in Accept-Encoding header (assuming no q factor). This is as per HTTP specs.

    It may be true that the client can specify a preference, and the preference is in presentation order, but, the server administrator may have a different preference. That is why it is stated as a preference order. And yes, there are good reasons for picking one over the other in specific circumstances.

  8. George
    November 24, 2007

    In IIS6, I can add *.jsp as a file type for dynamic content compression.

    For IIS7, I do not need to worry about the file type for dynamic, thery are all enabled, right?

    Thanks,

  9. ksingla
    November 27, 2007

    George,

    In IIS7, you can enable/disable compression based on mime-types. So instead of adding *.jsp, you need to enable dynamic compression for its mime-type by editing configuration in system.webServer/httpCompression section under dynamicTypes element. If you want to enable dynamic compression for all mime types, you can allow dynamic compression for */* mime-type. By default, dynamic compression is enabled for text/* and message/* mimetypes and not for all (mime-type */* has enabled="false").

    Kanwal

  10. ksingla
    November 27, 2007

    Mike,

    I am not sure why you think that javascript won't work on a webpage in IIS7. Javascript will work just fine on IIS7. Javascript is just another file and we send it across on http. Its http clients responsibility to request the files and interpret them all correctly.

    Kanwal

  11. ksingla
    November 27, 2007

    Spenser,

    Other than HcPriority and HcFilesDeletedPerDiskFree , other knobs were deleted because they pretty much don't make any sense given the design changes. I agree than scheme priority can be useful in some cases but we choose to stay compliant with http specs instead.

    Kanwal

  12. burçlar
    December 11, 2007

    Astroloji, günlük burçlar, burç uyumları, yükselen burçlar, aşk ölçer, haftalık burçlar, aylık burçlar, aşk falı testi, burç uyumu.

  13. carsamba
    January 10, 2008

    Danke

  14. carsamba
    January 10, 2008

    Javascript won't work on a webpage in iis7 ?

  15. ksingla
    January 10, 2008

    Hi carsamba,

    Javascript will work perfectly in IIS7. I am not sure why you got the impression that javascript won't work.

    Kanwal

  16. Microsoft.com Operations
    January 18, 2008

    Most operational folk are heads down either fixing issues, implementing new changes, or preparing environments

  17. gunok
    August 10, 2008

    hi ;

    We have a very busy server and IIS Compression disables mostly in daytime. We want it to be open what ever it costs. Because of not being want to consuma that much bandwith.

    We even did make

    dynamicCompressionDisableCpuUsage="99"                                  dynamicCompressionEnableCpuUsage="1">

    But how can I complettly shut of the disabling system ?

    Thank you very much

  18. ksingla
    August 19, 2008

    Hi gunok,

    There is no separate knob to completely shutoff the disabling system. If you change dynamicCompressionDisableCpuUsage and staticCompressionDisableCpuUsage to 100, that will effectively turn this system off because cpu usage will never be more than 100%. I don't think you need to set dynamicCompressionEnableCpuUsage and staticCompressionEnableCpuUsage but you can set them to 99/100 telling the system to enable it back if usage falls below 99%/100%.

    Thanks,

    Kj

  19. Noticias
    August 29, 2008

    Para utilizar mas eficientemente el ancho de banda disponible, usted puede activar la compresi&oacute;n

  20. Anonymous
    September 13, 2008

    Have you seen an situation where event ID 2264 is logged hourly?

    "The directory specified for caching compressed content C:\inetpub\temp\IIS Temporary Compressed Files\DefaultAppPool is invalid.  Static compression is being disabled"

    can you explain how this might be related to any changes in IIS7?

  21. how to enable the compression on IIS7 « nilleb’s tech blog
    October 4, 2008

    Pingback from  how to enable the compression on IIS7 &laquo; nilleb&#8217;s tech blog

Page view counter