12

Using Firebug and Chrome developer tools, I can see loading some javascript and css files through an action can take an extra 500ms on my development machine. This happens to different files on different calls and doesn't matter what order I put them in. If I link directly to the files this 500ms delay doesn't ever occur. I can refresh the page over and over and get different values, but they always look like 500ms was added to the request time. If I keep refreshing the page, the extra 500ms shows up on different single files or sometimes two files where one is a 1000ms delay like in the image below.


EDIT

Putting Monitor.Enter in my HttpModule's BeginRequest and Monitor.Exit in the EndRequest caused the delay to go away, so my guess is it has something to do with threading multiple requests.


I use the method descibed by Evan Nagel here for caching, but the same thing happens when I replace the links with calls to my own controller with an action that just passes a raw file through:

public FileResult RawFile(string path, string contentType)
{
    var server = HttpContext.Server;
    string decodedPath = server.UrlDecode(path);
    string mappedPath = server.MapPath(decodedPath);
    return File(mappedPath, contentType);
}

Here's the code I have in the head section of my html:

<link rel="stylesheet" href="@Url.Action("RawFile", new { controller = "Content", path = "~/Content/Site.css", contentType = "text/css" })" type="text/css" />
<script src="@Url.Action("RawFile", new { controller = "Content", path = "~/Scripts/debug/FBINFO.js", contentType = "application/x-javascript" })" type="text/javascript"></script>
<script src="@Url.Action("RawFile", new { controller = "Content", path = "~/Scripts/jquery-1.4.1.min.js", contentType = "application/x-javascript" })" type="text/javascript"></script>

This doesn't seem to happen on my production server, at least not as often but it is harder to tell because the latency is higher normally. Is this something not to worry about? What would cause it? It happens both with Cassini and with my local IIS server on Windows 7 Home Ultimate 64 bit.

I've added a custom attribute to time the calls and the times between OnAction/OnResult Executing and Executed are generally sub-millisecond. I've used a stopwatch around the action method (the ZipController writes to the response stream and doesn't return a result) and the times are likewise always small, average 1.5ms and always under 10ms.

The only real difference I can see in the Fiddler headers is the X-AspNetMvc-Version header, so I set it to not be appended and even removed the X-AspNet-Version header to no avail. I've tried enabling and disabling compression and about everything else I can think of too. This is after I added my own Cache-Control and ETag headers which had no effect. Interestingly the 500ms delay happens even in the case of a 304 Not Modified response where the body is not sent. Sometimes two of the files will have delays, one 500ms and the other 1000ms.

Direct file:

HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Sun, 29 May 2011 22:42:27 GMT
Accept-Ranges: bytes
ETag: "b57a84af511ecc1:0"
Server: Microsoft-IIS/7.5
Date: Mon, 30 May 2011 04:38:20 GMT
Content-Length: 1336

RawFile action:

HTTP/1.1 200 OK
Cache-Control: public
Content-Type: application/x-javascript
ETag: "CD9F383D0537373C6D2DC8F60D6519A6"
Server: Microsoft-IIS/7.5
Date: Mon, 30 May 2011 04:34:37 GMT
Content-Length: 1336

Action Method Direct File

Following IanT8's comment, I added an HttpModule to track begin/end request, as well as adding log calls as the first and last statements of my action methods. Long story short both requests come in at the same time and the 500ms delay occurs after the first EndRequest, before the action method of the second call is executed. This delay is usually 499ms, but it was 497ms once, 498ms once and 492ms once.

2011-05-31 00:55:19.1874|INFO|20110531 00:55:19.196 BeginRequest: http://localhost:51042/Zip/Style?Path=~/Content/Site.css
2011-05-31 00:55:19.1874|INFO|20110531 00:55:19.197 BeginRequest: http://localhost:51042/Zip/Script?Path=~/Scripts/jquery-1.4.1.min.js|~/Scripts/debug/FBINFO.js
2011-05-31 00:55:19.2034|INFO|20110531 00:55:19.203 Style() Start
2011-05-31 00:55:19.2034|INFO|20110531 00:55:19.208 Style() End
2011-05-31 00:55:19.2034|INFO|20110531 00:55:19.212 EndRequest: http://localhost:51042/Zip/Style?Path=~/Content/Site.css
2011-05-31 00:55:19.7044|INFO|20110531 00:55:19.704 Script() Start
2011-05-31 00:55:19.7044|INFO|20110531 00:55:19.712 Script() End
2011-05-31 00:55:19.7044|INFO|20110531 00:55:19.713 EndRequest: http://localhost:51042/Zip/Script?Path=~/Scripts/jquery-1.4.1.min.js|~/Scripts/debug/FBINFO.js

Now for the really interesting part. I created a static object on my HttpModule and called Monitor.Enter in the BeginRequest and Monitor.Exit in the EndRequest. The delay dissappeared. Chrome shows one call taking about 15-20ms and the other taking about 30-40ms because it has to wait for the first call to end, but the 500ms delay is gone. Obviously this solution is not optimal.

Jason Goemaat
  • 27,053
  • 14
  • 78
  • 109
  • Have you considered compilation time of the actions? You can test this by checking subsequent calls. – Buildstarted May 30 '11 at 05:50
  • Yes, I'll add a note to the question. – Jason Goemaat May 30 '11 at 06:01
  • 1
    Could it have anything to do with this limit I found mentioned on Server Fault? Would MS really want to make our development machines virtually useless for testing of this sort? The nearly exact 500ms added to each call makes me think it might be something like that. http://serverfault.com/questions/133772/what-about-windows-7-as-a-web-server – Jason Goemaat May 30 '11 at 06:46
  • I know when debugging in Firefox I expieriance high latency when using localhost to view the page, however when using 127.0.0.1 it is much faster. Could this be the same for Chrome? – Alex Hope O'Connor May 30 '11 at 06:49
  • 2
    Have you considered adding an Http Module to time and log the time spent, by hooking the begin request / end request events. At least you would then know how much time is being spent inside asp.net mvc. – IanT8 May 30 '11 at 08:42
  • IanT8 see my new comments, the delay is between one EndRequest and before the next action is actually executed. Using Monitor to keep them from executing simultaneously prevents the issue from happening. – Jason Goemaat May 31 '11 at 18:39

2 Answers2

6

Try to disable session (SessionStateAttribute).

bzlm
  • 9,198
  • 5
  • 59
  • 86
A_HREF
  • 331
  • 1
  • 8
  • That keeps it from happening, but I really want to use the session variable... Do you think it is an MVC bug? – Jason Goemaat Jun 08 '11 at 04:41
  • @Jason Requests to session-using actions are always serialized in ASP.NET to avoid concurrency issues. Do you really need session state for these requests to static files? – bzlm Jun 10 '11 at 16:23
  • Ah, for some reason I missed that it was an attribute and only knew how to disable it for everything in Web.config. Using the attribute worked. – Jason Goemaat Jun 10 '11 at 23:28
  • What do you mean by serialized? Why would it cause a 500 ms delay? – Jason Goemaat Jun 11 '11 at 06:57
  • @Jason I mean that requests from the same session (ie. the same user) to an action (or web form, in ASP.NET Web Forms) that uses session state are by default processed after each other. This is because the session state for one user could otherwise be mutated by two different ASP.NET worker threads simultaneously, which would likely lead to disaster. This would not incur a 500 ms delay, but it might still be relevant here, since one request would "wait for the other". (I can't provide a proper citation here because I couldn't find one.) – bzlm Jun 11 '11 at 09:27
  • That is what I thought, I wonder if MVC has some code that sleeps for 500ms if the session s locked already. I couldn't find any Sleep calls in the code but I didn't follow their code all the way through a request to see if there were any other locking calls that might cause a wait like that. – Jason Goemaat Jun 11 '11 at 22:32
  • Thank you!!! I have been troubleshooting the same issue today and this made all the difference in the world. I have a controller serving files and it was a real bottleneck since I hadn't disabled sessionstate. Lifesaver! – Jonatan B Nov 14 '12 at 16:35
  • I have a similar issue, but the `[SessionStateAttribute]` does not solve in my case.. :-( – T-moty Jan 19 '16 at 08:52
  • We had similar problem, but with loading a PartialView with AJAX. Disabling session (we do not use it) solves the latency issue. Thanks a lot ! – Tristan Djahel Apr 04 '19 at 14:37
0

There is a known issue with Cassini and performance related issues to IPv6 host file mapping over IPv4, and the port number resolution that Cassini uses under Windows 7. It is already answered on Stack Overflow and solves issues seen in Firefox and Chrome.

Community
  • 1
  • 1
Rebecca
  • 12,888
  • 10
  • 84
  • 127