Connell
Connell

Reputation: 14411

MVC 4 IIS memory leak for each connection

I have an AsyncController set up to perform long-polling actions. This all works fine, however a colleague has noticed a memory leak on the server that appears to increase with every new connection.

I've created a little application to request from this page thousands of times and I'm monitoring the memory usage for the IIS process. Each connection increases the memory usage but doesn't fall back down when the client has disconnected.

After further investigation, I found that this still happens even when I replace my AsyncController with a standard Controller that does nothing but this:

public class WaitController: Controller
{
    public JsonResult Member(string oauth_token, int service_id, bool busy = false)
    {
        return Json(new
        {
            ready = false,
        }, JsonRequestBehavior.AllowGet);
    }
}

Although there is not as much memory usage in this, the behavior appears to be exactly the same.

I've run a memory profiler to show the difference between 10,000 connections and there is barely anything there. The most memory is taken up by instances of ExpiresEntry[] from System.Web.Caching or System.Runtime.Caching, however these total to nothing in comparison to the memory increase I'm getting on the IIS worker process.

My question is, is IIS doing this by design? Perhaps this had been allocated for connection threads, which are hanging around just in case they're needed later? Is this a bug with IIS, ASP.NET, or MVC 4?

I decided to use MVC 4's WebAPI features for this because we want this to be flexible, maintainable, future-proof, and accessed via AJAX. It also seemed to make sense from a development point of view, as we have built the website in MVC 4 too.

However, a colleague has now raised this as a critical problem with the system architecture as we will (in the future) need thousands of clients connected. He is suggesting we use WCF instead. So, bonus question - will using WCF resolve these problems?

Upvotes: 6

Views: 3663

Answers (2)

Connell
Connell

Reputation: 14411

After more experimenting and testing, I've discovered this, unfortunately, cannot be prevented. It seems to be either by design or a real deep-rooted issue with IIS.

I changed my method to use a lower-level option: Implement an IHttpAsyncHandler to do the same thing. I used a custom HttpHandler route for MVC to allow me to use the exact same URLs as I was using before. The problem still existed, but on a slightly smaller scale.

I then tried a completely blank IHttpHandler that simply returns { ready: false } (as my code would do on a timeout). No other code included in the HttpHandler, but the same issue still occurs.

Next, I tried a completely blank WCF service that also returned { ready: false }. Same issue, but on an even smaller scale this time.

As the link @rusev's answer suggests:

Memory fragmentation and other natural degradation cannot be avoided and recycling ensures that the applications are periodically cleaned up.

This may be the cause of the problem. I can imagine that because there are more overheads when using an MVC Controller, the fragmentation just happens faster. Using lower-level methods such as an HttpHandler or a WCF service would use less memory per connection, therefore cause less fragmentation.

Upvotes: 0

rusev
rusev

Reputation: 1920

There's a great article from a MS Field Engineer about this subject. Might be of help.

Upvotes: 1

Related Questions