First call to Url.Action on a page is slow

怎甘沉沦 提交于 2019-12-06 02:05:36

问题


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?


回答1:


Problem found, and it is with the routing tables (cheers Kirill).

Basically we have lots of routes that look something like this:

string[] controllers = GetListOfValidControllers();

routes.MapRoute(
    name: GetRouteName(),
    url: subfolder + "/{controller}/{action}/{id}",
    defaults: new { action = "Index", id = UrlParameter.Optional },
    constraints: new { controller = "(" + string.Join("|", controllers) + ")" });

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 a HashSet instead.

Then I changed the map route call:

routes.MapRoute(
    name: GetRouteName(),
    url: subfolder + "/{controller}/{action}/{id}",
    defaults: new { action = "Index", id = UrlParameter.Optional },
    constraints: new { controller = new HashSetConstraint(controllers) });

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):

routes.IgnoreRoute(
    url: "{*allaspx}", 
    constraints: new { allaspx = new RegexConstraint( @".*\.as[pmh]x(/.*)?") });

Those two simple changes completely fix the problem; Url.Action and Html.BeginForm now take a negligible amount of time (even with lots of routes).




回答2:


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




回答3:


    public class RegexConstraint : IRouteConstraint, IEquatable<RegexConstraint>
     {
    Regex regex;
    string pattern;

    public RegexConstraint(string pattern, RegexOptions options = RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase)
    {
        regex = new Regex(pattern, options);
        this.pattern = pattern;
    }

    public bool Match(System.Web.HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        object val;
        values.TryGetValue(parameterName, out val);
        string input = Convert.ToString(val, CultureInfo.InvariantCulture);
        return regex.IsMatch(input);
    }

    public string Pattern
    {
        get
        {
            return pattern;
        }
    }

    public RegexOptions RegexOptions
    {
        get
        {
            return regex.Options;
        }
    }

    private string Key
    {
        get
        {
            return regex.Options.ToString() + " | " + pattern;
        }
    }

    public override int GetHashCode()
    {
        return Key.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as RegexConstraint;
        if (other == null) return false;
        return Key == other.Key;
    }

    public bool Equals(RegexConstraint other)
    {
        return this.Equals((object)other);
    }

    public override string ToString()
    {
        return "RegexConstraint (" + Pattern + ")";
    }
}


来源:https://stackoverflow.com/questions/11900134/first-call-to-url-action-on-a-page-is-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!