I have a performance issue with a fairly simple ASP.MVC view.
It's a log-on page that should be almost instant, but is taking about half a second.
After a lot of digging it looks like the problem is the first call the Url.Action
- it's taking around 450ms (according to MiniProfiler) but that seems insanely slow.
Subsequent calls to Url.Action
are taking <1ms, which is more in line with what I would expect.
This is consistent whether I use Url.Action("action", "controller")
or Url.Action("action")
, but doesn't seem to happen if I use Url.Content("~/controller/action")
. This also happens when I call Html.BeginForm("action")
.
Does anyone have any idea what's causing this?
A dig into the source suggests that RouteCollection.GetVirtualPath
might be the culprit, as that's common to both Url.Action
and Html.BeginForm
. However, surely that's used all over the place? I mean, ½ a second is far too slow.
I have 20 or so custom routes (it's a fairly large app with some legacy WebForms pages) but even then the times seem far too slow.
Any ideas how to fix it?
It seems to me that your problem is compiling of views. You need to precompile views on build and this problem will gone. details here
I've stripped it to "bare-bones"... set a single file into memory and downloading it from the action compared to downloading it from IHttpModule. IHttpModule is much faster (for small files, e.g. product list images) for some reason (probably MVC pipeline load, routing). I don't have regex used in routing (that slows it even more). In IHttpModule I am reaching the same speeds as if URL is pointing to file on a drive (of course that is if the file is on the drive but not on the drive location that URL points to).
Problem found, and it is with the routing tables (cheers Kirill).
Basically we have lots of routes that look something like this:
It turns out that the Regex check is very slow, painfully slow. So I replaced it with an implementation of
IRouteConstraint
that just checks against aHashSet
instead.Then I changed the map route call:
I also used the RegexConstraint mentioned in that linked article for anything more complicated - including lots of calls like this (because we have legacy WebForm pages):
Those two simple changes completely fix the problem;
Url.Action
andHtml.BeginForm
now take a negligible amount of time (even with lots of routes).