Search code examples
asp.net-mvcsessionwebformshttpsession

Storing Anything in ASP.NET Session Causes 500ms Delays


The Problem:

When you use session in an ASP.NET site, it causes dramatic delays (multiples of 500ms) when loading multiple requests at nearly the same time.

More Specifically, My Problem

Our website uses session exclusively for its SessionId. We use this key to look up a db table that has user info, etc. This seemed to be a good design since it stored minimal session data. Unfortunately, the SessionId will change if you store nothing in session, so we store Session["KeepId"] = 1;. This is enough to convince SessionId to not change.

On a seemingly unrelated note, the site serves customized product images through a controller action. This action generates an image if needed then redirects to the cached image. This means that one web page may contain images or other resources, sending dozens of requests through the ASP.NET pipeline.

For whatever reason, when you (a) send multiple requests at the same time and (b) have session involved in any way then you will end up with random 500ms delays about 1/2 the time. In some cases these delays will be 1000ms or more, always increasing in intervals of ~500ms. More requests means longer wait times. Our page with dozens of images can wait 10+ seconds for some images.

How to Reproduce the Problem:

  1. Create an empty ASP.NET MVC Web Application
  2. Create an empty controller action:

    public class HomeController : Controller
    {
      public ActionResult Test()
      {
        return new EmptyResult();
      }
    }
    
  3. Make a test.html page with a few img tags that hit that action:

    <img src="Home/Test?1" />
    <img src="Home/Test?2" />
    <img src="Home/Test?3" />
    <img src="Home/Test?4" />
    
  4. Run the page & watch the fast load times in firebug:

    Each image loads reasonably fast

  5. Do one of the follow (both have the same result):

    • Add an empty Session_Start handler to your Global.asax.cs

      public void Session_Start() { }
      
    • Put something in session

      public class HomeController : Controller
      {
        public ActionResult Test()
        {
          HttpContext.Current.Session["Test"] = 1;
          return new EmptyResult();
        }
      }
      
  6. Run the page again & notice the occasional/random delays in the responses.

    Some requests experience long delays

What I Know So Far

My Question

How can I use session but avoid these delays? Does anyone know of a fix?

If there's not a fix, I guess we'll have to bypass session & use cookies directly (session uses cookies).


Solution

  • As Gats mentioned, the problem is that ASP.NET locks session so each request for the same session must run in serial.

    The annoying part is if I ran all 5 requests in serial (from the example), it'd take ~40ms. With ASP.NET's locking it's over 1000ms. It seems like ASP.NET says, "If session is in use, then sleep for 500ms & try again."

    If you use StateServer or SqlServer instead of InProc, it won't help - ASP.NET still locks session.

    There are a few different fixes. We ended up using the first one.

    Use Cookies Instead

    Cookies are sent in the header of every request, so you should keep it light & avoid sensitive info. That being said, session uses cookies by default to remember who is who by storing a ASPNET_SessionId string. All I needed is that id, so there's no reason to endure ASP.NET's session locking when it's just a wrapper around an id in a cookie.

    So we avoid session completely & store a guid in the cookie instead. Cookies don't lock, so the delays are fixed.

    Use MVC Attributes

    You can use session, but avoid the locks on certain requests by making session read-only.

    For MVC 3 applications, use this attribute on your controller to make session read-only (it doesn't work on a specific action):

    [SessionState(SessionStateBehavior.ReadOnly)]
    

    Disable Session for Some Routes

    You can also disable session through MVC routing, but it's a bit complicated.

    Disable Session on a Specific Page

    For WebForms, you can disable session for certain aspx pages.