IIS 7 C++ Module API Sample: Controlling http.sys caching

IIS 7 C++ Module API Sample: Controlling http.sys caching

Introduction

In my previous post we saw that http.sys caching can be very useful for high traffic (gigabits/sec) sites. In this post we create a sample module that allows configuring which URLs can enter the cache.

Code

There is very little non-template, IIS-specific, code in this module. In fact here is everything that is important:
REQUEST_NOTIFICATION_STATUS
MODULE::OnSendResponse(
    IHttpContext*           pContext,
    ISendResponseProvider*  pProvider
)
{
    if( !pProvider->GetHeadersBeingSent( ) )
    {
        //
        // headers not being sent, not first send response notification, nothing to do
        //
        goto Finished;
    }

    if( !g_pUrlHash->Exists( pContext->GetScriptName( ) ) )
    {
        //
        // not a pre-determined "hot" url, no caching..
        //
        IHttpResponse* pResponse = pContext->GetResponse( );
        pResponse->DisableKernelCache( 123 );
    }

Finished:

    return RQ_NOTIFICATION_CONTINUE;
}
Important points:
  • RQ_SEND_RESPONSE is a "non-deterministic" notification that can fire multiple times (e.g. whenever someone calls IHttpResponse::Flush). To determine the first time we're being notified, the module checks ISendResponseProvider::GetHeadersBeingSent. This is only true on the first notification for the request.
  • IHttpContext::GetScriptName is often the URL you want to compare to. It has been "sanitized" and had PATH_INFO removed.
  • IHttpResponse::DisableKernelCache trumps any cache policy configured with IHttpResponse::GetRawHttpResponse()->...

Setup

As mentioned, there are many caches and caching algorithms in IIS. To simplify the testing of this module I:
  • disabled my file cache module (simply removed it from the pipline - "appcmd uninstall module FileCacheModule").
  • disabled the "hotness" detection algorithm in iiscore ("appcmd set config -section:serverRuntime -frequentHitThreshold:1")

Test

This time I'm using a newer dual-core machine with 1GB ram and running the perf client locally. There are 4000x184kb "hot" files, and 4000x184kb "cold" files. Total = 8000x184kb = 1.4GB. Hot files are hit 32x more frequently than cold files. For the Cacheit test, I installed the module and only gave it the full list of 4000 hot URLs.

Test Req/s Cache Content
    Hot Cold
Baseline 770 3994 765
Cacheit 833 (+8%) 4001 13

Request/sec came from wcat's log. Cache contents was determined by running "netsh http show cachestate > out.txt" and then "findstr /i hot out.txt" and "findstr /i cold out.txt".

Conclusion

The optimistic conclusion is that we've learnt about a new way of using the module APIs as well as tried out a common thought experiment (what would happen if my cache new exactly what to cache). Another conclusion is that, with the exact scenario under consideration, there are probably very very few cases where this would be useful.

No Comments