Узкое место в производительности Url.Action -можно ли обойти это?

У меня есть приложение, которое я недавно обновил с ASP.NET MVC1 до ASP.NET MVC4 rc1.

Он использует механизм просмотра Webforms.

У него возникают проблемы с производительностью всякий раз, когда используется действие Url.Action (, контроллер ).

Я могу воспроизвести проблему в ASP.NET MVC3.

Мне нужно 3 мс для рендеринга представлений с 10 экземплярами помощника Url.Action в ASP.NET MVC1 и 40 мс для рендеринга того же в ASP.NET MVC3.

Я уже нашел несколько способов ускорить рендеринг:

  • Я переместил маршрут по умолчанию наверх

  • Я удалил Url.Action и использовал статические ссылки

Это кажется неправильным :приложение довольно большое, и мне нужна хорошая работающая маршрутизация в нем. Я также не уверен, что нашел все узкие места производительности. Маршрутизация является центральной частью MVC :. Если что-то работает плохо, это всплывет в разных частях приложения.

У меня сложилось впечатление, что MVC3 представил некоторые функции маршрутизации (, такие как ограничения регулярных выражений ), которые, даже если я их не использую, приводят к плохой работе приложения.

Есть ли что-то, что я могу сделать, например отключить функции маршрутизации или использовать другой набор помощников URL -?

Этот код воспроизводит проблему:

Индексное действие

public ActionResult Index()
        {

            return View();
        }

index.aspx

<%@ Page Language="C#"  Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head >
    <title></title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <div class="page">
<%= Url.Action("Action1", "Controller1") %>
<%= Url.Action("Action2", "Controller2") %>
<%= Url.Action("Action3", "Controller3") %>
<%= Url.Action("Action4", "Controller4") %>
<%= Url.Action("Action5", "Controller5") %>
<%= Url.Action("Action6", "Controller6") %>
<%= Url.Action("Action7", "Controller7") %>
<%= Url.Action("Action8", "Controller8") %>
<%= Url.Action("Action9", "Controller9") %>
<%= Url.Action("Action10", "Controller10") %>
    </div>
</body>
</html>

Регистрация маршрута Это выглядит странно :, но я просто хочу смоделировать свою не очень сложную маршрутизацию. Это не 600 маршрутов ТАК!

public static void RegisterRoutesSlow(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{language}/Content/{*pathInfo}");

    routes.IgnoreRoute("images/{*pathinfo}");
    routes.IgnoreRoute("scripts/{*pathinfo}");
    routes.IgnoreRoute("content/{*pathinfo}");
    routes.IgnoreRoute("{file}.gif");
    routes.IgnoreRoute("{file}.jpg");
    routes.IgnoreRoute("{file}.js");
    routes.IgnoreRoute("{file}.css");
    routes.IgnoreRoute("{file}.png");
    routes.IgnoreRoute("{file}.pdf");
    routes.IgnoreRoute("{file}.htm");
    routes.IgnoreRoute("{file}.html");
    routes.IgnoreRoute("{file}.swf");
    routes.IgnoreRoute("{file}.txt");
    routes.IgnoreRoute("{file}.xml");
    routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

    for (int i = 0; i <= 10; i++)
    {
        routes.MapRoute(
            // Route name
            "RouteName" + i.ToString(),
            // URL with parameters                              
            "{language}/{controller}/{action}/{para1}",
            // Parameter defaults
            new
            {
                action = "Index",
                language = "de",
                para1 = 0
            },
            //Parameter constraints
            new { language = "de|en", controller = "SomeNameOfAnActualController" + i.ToString() }
            );
    }
    routes.MapRoute(
                   "DefaulRoute",            // Route name
                   "{controller}/{action}",    // URL with parameters
                   new
                   {
                       controller = "Home",
                       action = "Index",
                   }
               );
    routes.MapRoute("404-PageNotFound", "{*url}", new { controller = "Error", action = "PageNotFound", language = "de" });
}

РЕДАКТИРОВАТЬ

Образец кода теперь скомпилирован для MVC2. В VS2010 MVC2 можно скомпилировать с.NET 3.5 или 4.0.

Производительность с 3.5 хорошая, а с 4.0 плохая.

Я предполагаю, что это означает, что плохо работающая часть находится не в сборке MVC, а в сборке фреймворка (, такой как System.Web.Routing.dll ). Вопрос все тот же :Можно ли что-то с этим сделать? Принятым ответом также будет :Нет, код медленный, потому что с версии 3.5 на 4.0 MS изменилось XXX

РЕДАКТИРОВАТЬ -2

Я декомпилировал часть System.Web.Routing.dll, которая занимает много времени. Он использует скомпилированное регулярное выражение. Существует путь кода (ограничение2.Match ), который возвращает без выполнения регулярного выражения, но я еще не проверял, использует ли он внутри другую дорогостоящую операцию.

protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
    object obj2;
    IRouteConstraint constraint2 = constraint as IRouteConstraint;
    if (constraint2 != null)
    {
        return constraint2.Match(httpContext, this, parameterName, values, routeDirection);
    }
    string str = constraint as string;
    if (str == null)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("Route_ValidationMustBeStringOrCustomConstraint"), new object[] { parameterName, this.Url }));
    }
    values.TryGetValue(parameterName, out obj2);
    string input = Convert.ToString(obj2, CultureInfo.InvariantCulture);
    string pattern = "^(" + str + ")$";
    return Regex.IsMatch(input, pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
7
задан Mathias F 16 August 2012 в 21:30
поделиться