Speeding up your application with the IIS Auto-Start feature

Red Gate recently polled the ASP.NET developer community for tips on improving the performance of ASP.NET web applications. The result was an excellent free e-book entitled “50 Ways to Avoid, Find and Fix ASP.NET Performance Issues”. The book is full of quick and easy tips to squeeze some added performance from your ASP.NET applications, and if you haven’t had the chance to check it out yet you can download it for free from here.

Being a bit of a performance nut myself, I jumped at the opportunity to share a few tips of my own. One of these was a little known tip on preventing the delay that commonly occurs from a cold hit on an ASP.NET website running on IIS. This tip seemed to strike a chord with a few developers so I’ve decided to expand on it here.

The First Hit

Have you ever thought that the first request to your ASP.NET application seems to take much longer than others? If so, then you’re not imagining things…it actually does. That’s because to maximize resources IIS doesn’t keep all sites on an instance running at all times. In fact, the AppDomain for a website on IIS is not loaded until its needed and, by default, will eventually be unloaded after a period of inactivity.

It’s this lazy-loading of websites that causes the first request to an ASP.NET site to take so much longer than others. Since the site hasn’t been accessed yet, it must first be loaded by IIS before ASP.NET can properly respond to the request.

Luckily there is a solution. Auto-Start, introduced with IIS 7.5, allows an ASP.NET application deployed to IIS to be available immediately after deployment. In the simplest sense, enabling this feature causes IIS to prime an application as soon as it is deployed removing the warm-up time often required of “cold hits” to a website. In this article we’ll see how we can enable this feature either through IIS Manager or configuration files and even how we can perform more advanced application warm-up routines, such as priming a cache.

Configuring Auto-Start with IIS Manager

Enabling Auto-Start via IIS is actually quite simple, though the settings can be tricky to find the first time.

  1. Open Internet Information Services (IIS) Manager.
  2. In the Connections pane, select the Application Pools node, revealing the Application Pools pane in the main view.
  3. Select the application pool for which you wish to enable Auto-Start.

    IIS-autostart1.png

  4. Click Advanced Settings…
  5. Locate the Start Mode option under the General group and set it to AlwaysRunning. IIS-autostart2.png
  6. Click OK.

That’s it! Now the website hosted by the application pool you just modified will always be instantly available, even after extended periods of activity.

Configuration Auto-Start with applicationHost.config

Enabling Auto-Start using the IIS Manager UI is quick and simple, but tweaking the settings for all of your application pools via the user interface may not be scalable. For example, imagine that you were rolling out your website to a large web server farm and need to automate the configuration of all your application pools.

In this case, we can also enable Auto-Start by tweaking the applicationHost.config file which controls the application domains for all instances running on that server. applicationHost.config can be found at <Windows>\System32\inetsrv\config\applicationHost.config.

Inside of the applicationHost.config file, locate the <applicationPools> node located under <configuration>/<system.applicationHost>. Inside of the <applicationPools> node, locate the entry whose name attribute corresponds to your application pool, and add a startMode attribute with the value of “AlwaysRunning“.

The addition of the startMode attribute will override the default start mode of “OnDemand“.

Advanced Application Warm Up with Auto-Start

We’ve seen how to work around the “cold-hit” problem that often affects websites running on IIS. However, imagine that early requests to your site can still cause delays, perhaps due to expensive data that has to be retrieved. In these cases you can certainly cache the data after it’s retrieved to make subsequent requests faster, but the unlucky visitor who first makes the request still has to bear the brunt of the work for others.

While in the past it wasn’t unheard of for developers to prime their caches with these expensive data requests in the Application_Start() function of Global.asax.cs, IIS now provides a cleaner way through the use of Auto-Start Providers.

For example, let’s imagine that the home page of your application contains a rather expensive call. In the fact, the call is so expensive that we’ve elected to cache the results improve the performance of subsequent requests. However, this still lays the bulk of the work at the feet of the site’s first visitor.

While this technique does improve the performance for subsequent visitors, it still lays the bulk of the work at the feet of the site’s first. However, IIS now provides a better place to perform these types of warm-up tasks.

Preload clients, which implement the IProcessHostPreloadClient interface, contain a single method Preload(…) which can be used to cleanly perform these warm-up tasks.

However, this class will not be loaded automatically. We need to tell IIS both about the existence of this class as well as which website it applies to. To do this, we’ll need to return to our applicationHost.config file.

First, we’ll need to add an element called <serviceAutoStartProviders> to the <configuration>/<system.applicationHost> node.

This element registers our custom preload client with the name MvcMusicStoreAutoStartProvider. Be sure to fully qualify the type name in the type attribute so the assembly loader can locate it.

Finally, we’ll locate the entry for our site under the sites node and register our preload client in our site’s application node.

This is done by adding the serviceAutoStartEnabled attribute, set to true, and by adding the serviceAutoStartProvider attribute, set to the name of the serviceAutoStartProvider entry we added in the previous step.

Wrapping Up

With just a few easy steps we’ve ensured that our application is always ready to go when a user a visits. In addition, we’ve also discovered an easy way to offload time intensive operations, such as priming a cold cache, from the first user to the initial startup of the application. With these two tips in hand we’re sure to have a fast and responsive application that our users will rave about.