Chris
Chris

Reputation: 4485

ASP.NET MVC: First access after some minutes slow, then every following request is fast

when I access any page of my ASP.NET MVC website first time, then this first request is slow. It needs about 4-5 seconds to load. But every following request to any page is fast.

When I wait some minutes or a hour then every first request is slow again. Every following request is fast.

I think that IIS 7 is compiling the code and keep it in memory. After some time it will delete it from memory so it needs to compile it again.

What can I do that every first request is as fast as every following request? (Without precompiling my source, if possible)

Thank you very much in advance!

Upvotes: 26

Views: 16732

Answers (5)

davke
davke

Reputation: 360

tl; dr

After quite extensive testing and gathering of relevant sources to attempt to resolve the issue, I think that the minimal solution may be (not verified) to add this code to the global.asax:

    protected void Application_End()
    {
        ...
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://web_domain.tld");
        using (HttpWebResponse response = (HttpWebResponse)
            request.GetResponse())
        {
        }
        ...
    }

In the time of writing the post, this is used to effectevely maintain the site I worked on 'always-up' - with conjuction of setting the Idle Time-out (minutes) in IIS to 0 as mentioned in other answers. However I think that changing Idle Time-out (minutes) may not be necessary (assuming that Application_end event is raised when the switch of application pool to Idle mode occurs).

How it works (assuming it does):

  1. There are 2 settings in the IIS application pool settings that affect when the application is suspended or terminated. One of them is Idle Time-out (minutes) which defaults to 20 minutes and when the specified time elapses since the last request, the worker process is suspended or terminated. When a next request comes, the worker process is resumed or started again and the Application_start event is raised (and so if the Application_start handler is defined in global.asax, it is executed). In case of the project I worked on, the Application_start took about 17 seconds to complete. So if the site was 'left alone' for 21 minutes and then the new request came, it took about a little more than 17 seconds before the response was sent back (Application_start + page processing). When another request was sent in the window of 20 minutes, the response was sent significantly faster (perhaps less than 1s), since the Application_start has already been processed.

Setting the Idle Time-out (minutes) value to 0 causes the worker process to never be suspended / terminated (at least due to the idle time - there may be another cause described below).

  1. Apart from Idle Time-out (minutes), there is also the Regular time interval (minutes) setting in Recycling section of the IIS advanced settings. This defaults to 1740 minutes (29 hours) and is a regular scheduled task that causes the Application pool to periodically recycle (the period is fixed). This, I understood, is to prevent the accumulation of possible memory-leaks which, if present, may eventually crash the server by exhasting all the memory. The effect of app-pool recycling is that Application_end event is raised. However, after the application ends it is not automatically started again, so the Application_start event is not raised until an actual request comes (which is similar to the first case). So in the case of the aforementioned web application I worked on, it would again take about 17 seconds to process the first request to arrive after the recycling occured. Changing this value to 0 turns the recycling off, but I suppose that it is reasonable not to turn the recycling completely off due to the possibility of accumuluation of memory leaks over time (which may possibly even be caused by bugs in 3rd party libraries). I understand that the opinions differ on whether to set this value to 0 or not and may change over time.

Posible solution (without changing IIS settings): If the requests are sent frequently enough, the app-pool may never switch to Idle mode. On the event of recycling, this would also cause to the application to start again. This can be achieved, for example, by using 3rd party service as described by @Rippo.

Proposed solution: It has been observed that application pool recycling caused Application_end event to be raised. Assuming that it is also raised upon switching of the application pool to Idle mode, it would seem to be sufficient to create a request in the Application_end event handler to the website, which in both cases would then cause the application to start again (raising the Application_start event). The code is at the top of the answer.

Upvotes: 0

adamjcooper
adamjcooper

Reputation: 1141

This is almost-certainly your app pool idle timeout setting (and not your code being recompiled).

The default app pool idle timeout in IIS is 20 minutes. Which means that, if 20 minutes pass and no requests come in to your app, IIS will shut down the worker process for your app pool, making your app "cold" again. Whoever makes the next request will be waiting several seconds as IIS restarts the worker process and "warms" your app back up.

If you don't want IIS to automatically "cool down" your app after a period of inactivity, you can disable the app pool idle timeout by setting it to 0.

Upvotes: 5

Rippo
Rippo

Reputation: 22424

If this is a production server then why not try adding a website monitor; such as up time robot. It basically asks for your websites headers and gets status codes like "200-ok", "404-not found", etc. every 5 minutes. This way your site is always spun up and does not impact log files/analytics as only headers are requested. I use this for my cloud sites as I find that they take 5 seconds to spin up which has an impact on site loading. With the monitor they are instant.

Oh and its free for up to 50 sites!

Upvotes: 23

BlackICE
BlackICE

Reputation: 8916

This could be the recycle worker processes setting on the application pool, check the value for that and either turn it off or make it longer.

Could also be the Shutdown worker process after being idle under performance for the application pool.

It's probably the second as that defaults to 20 minutes, the first one defaults to 29 hours I believe.

Upvotes: 18

Cahit
Cahit

Reputation: 2534

Assuming that you have a regular stream of visitors, this should not be a problem in production. Also, unless you're physically altering any of your source files, IIS would not recompile it when it spins up your app.

Also, take a look at the .NET compilation settings available: http://technet.microsoft.com/en-us/library/cc725812(WS.10).aspx

Upvotes: 1

Related Questions