What to do about the slow startup of web services


Due to the architecture of web services and web applications they can be quite slow to start. For example on my Windows 2003-box the initial localhost-call to a simple “Hello World!”-web service takes approximately 8 seconds, while the next request is more or less immediate.

Why is this?

This isn’t news, really. One of the first things we learned in the early beta stages of ASP.NET was that the first request would take a little extra time due to the Just In Time Compilation (JIT). This was a major change from the classic ASP architecture where everything was interpreted rather than compiled. Upon the first request the .aspx / .asmx file will be compiled (JIT’ed) into Microsoft Immediate Language (MSIL) and the resulting .dll will be moved to it’s proper location.

This compilation will occur every time the application pool starts causing a significantly longer response time on the first request compared to the following requests.

Run-time performance over startup performance

It all comes down to prioritizing run-time performance over a quick startup. Which, in my humble opinion, is a sound choice. There are, however, situations where you may feel that this is to your disadvantage. The other day I got a question from a customer who had a web service that was called quite infrequently and to him this meant that with every other request response times would be horrendous, simply because the application got recompiled.

For each case I get I usually do a quick search on the problem description. I don’t really expect to find the solution this way, since I can only assume that the customer has tried this as well. Instead it will likely present me with a list of troubleshooting steps that the customer has already tried as well as possible solutions that didn’t fit. (Off course I still need to verify this with the customer).

This time I didn’t really need to do this since I was pretty sure what the cause was. Still, I was curious to see how common this problem was. I honestly didn’t think this was a very common scenario, but my quick search on the web revealed the contrary. The few hits that I quickly browsed through suggested writing an application that would ping the web service in order to keep it alive. I must admit I find this quite inventive, but I really don’t think it’s the best approach. 🙂

What to do

So, what is to be done about this? Well, I’ve already mentioned that there are better solutions than pinging the web service. As I told my customer there are basically two good options:

  1. Precompile the assemblies
  2. Change the settings for automatic recycling on the worker process

Precompiling the assemblies

There is a nice little tool called Native Image Generator. (ngen.exe) It will compile the assembly into native images and installs them into the native image cache. The syntax is pretty straight-forward: ngen.exe install [assembly] The problem is that once you’ve changed the assembly you’d have to precompile it again making updates a bit tedious.

There is also a service-version of the ngen called the Native Image Service. More information about ngen can be found at http://msdn2.microsoft.com/sv-se/magazine/cc163808(en-us).aspx

Changing the recycling settings

The reason why my customer was experiencing this problem was because his application pool would time out and recycle itself due to the default settings in the IIS manager. By default the worker process will recycle after 20 minutes of inactivity, so if no one has pinged your application in that time the next request will cause the application to recompile, resulting in a longer response time. By tweaking this setting in the IIS manager to something more suitable to the current rate of requests, like 40 minutes or maybe even 60 he should also be able to find a nice balance. Actually, considering the low load it would probably be a good idea to turn this setting off completely. Here’s how:

  • Open up IIS Manager
  • Locate the Application Pool in question
  • Right-click it and select “Properties”
  • Go to the “Performance”-tab
  • Change, or disable the “Idle timeout” setting

/ Johan

Comments (6)

  1. Josh L says:

    This article doesn’t mention it (perhaps it’s assumed) but you can pre-compile your asp.net pages by using Web deployment projects and unchecking "Allow this precompiled site to be updatable".  More information here:

    http://msdn2.microsoft.com/en-us/library/aa479568.aspx

    Ngen adds a number of complications, including ensuring that you don’t have any base address conflicts – see this article for more information:

    http://msdn2.microsoft.com/en-us/magazine/cc163610.aspx

  2. Fredy Feld says:

    I had the same problem. The reason is that the application domain times out every 20 mins if there is no activity, the first request after the timeout can force a recompile and reload of cache. Changing some settings in the machine.config file will solve the problem; unfortunately for me my hosting provider would not allow me to make this change. I found this utility to be useful.

    http://www.spikesolutions.net/ViewSolution.aspx?ID=c2b7edc0-5de1-4064-a432-05f6eded3b82

    Essentially it "Pings" my home page every few mins so the application domain does not time out. The utility can also be configured to ping more than one page so that auxiliary pages are fast too.

  3. Dan Ribar says:

    I found that when the website [calling the web service] has debug="true" in the web.config,  it loads and does the JIT compilation and takes a while on the first load.  

    Sitching the debug to "False" eliminates the problem.  BTW,  I also have set the worker processes to NOT restart,  but we learned that many moons ago when we were deploying SSRS.  It tends to do the same thing on reports starting slowly for the first time.

    Dan Ribar

  4. Vinny says:

    Dan

    Spot on. Had a similar problem with pages taking minutes to initially load,  and all along it was the web.config file that was the problem. Changing debug="true" to debug="false" corrects the issue and the pages load almost instantly.

    Thanks for the tip.

    Vinny Hassell

  5. Prashanth says:

    try setting the proxy to an empty WebProxy, ie:

    request.Proxy = new WebProxy();

    or you can override the proxy settings in the .Config file for your application using the defaultProxy key in the system.net section. The following disables automatic Proxy detection:

    <configuration >

     <system.net>

       <defaultProxy>

         <proxy bypassonlocal="true" usesystemdefault="false" />

       </defaultProxy>

    </system.net>

    </configuration>

    weblog.west-wind.com/…/Slow-Http-client-calls-from-ASPNET-20-Make-sure-you-check-your-Proxy-Settings

  6. Rez says:

    Thank you sir, incredibly helpful post.