The row above decreased the load time from 30 seconds to 5 seconds. Yes. Let me explain.
I've built a standard MVC project that uses Ajax, a lot. When a page loads, I'm firing like 6-10(depending on how many modules the site contains) simultaneous Ajax requests to different controllers to fetch data from my web api. I noticed a few really weird problems:
- I couldn't navigate to another page until all Ajax requests were completed, dafuq?
- The calls were made in parallel from the client, but the server did NOT execute them in parallel, dafuq?
I started googling, no, that's a lie, first I started to question myself, my skills and my life and then I cried/raged for a bit.
After that, me and my colleagues brainstormed a bit:
- "Could it be that we are using up all the threads?"
- "The calls are blocking somehow, test async await?"
I spent a full day rebuilding our API to make it asynchronous and I was fully convinced that this would solve our problems, GREAT!
It. Did. Not.
After crying for a day or two I started googling. A lot. It turned out that... I was not alone.
I found this article written by John Culviner
One of the first sentences in that article got my attention:
It appeared that if I shot off Ajax Request A, B, C, D… that they would always return one after the other (roughly).
Hmm...is he onto something here?
He linked to the following article(written by Microsoft...)
Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.)
I don't know why this affects my application because I don't use sessions but I guess that this serialization always happens if there are concurrent requests...?
Anyhow...by setting SessionState(SessionStateBehavior.Disabled) as an attribute on my BaseController, the response time went from 30 to FIVE seconds. I set it to Disabled because I don't use sessions at all. I tried setting it to ReadOnly as well and that also solved the problem.
So what have we learned from this? Well...I don't usually use sessions, so my BaseController will from now on ALWAYS use SessionState(SessionStateBahavior.Disabled).