У меня есть приложение, которое я недавно обновил с ASP.NET MVC1 до ASP.NET MVC4 rc1.Узкое место производительности Url.Action - могу ли я обходным путем?
Он использует Viewview Webforms.
У этого есть проблемы с производительностью, когда используется Url.Action (действие, контроллер).
Я могу воспроизвести проблему в ASP.NET MVC3.
Мне нужно 3 мс для рендеринга представлений, в которых есть 10 экземпляров помощника Url.Action в ASP.NET MVC1 и 40ms для визуализации того же самого в 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 маршрутов SO!
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" });
}
EDIT
Код образца был составлен против MVC2 в настоящее время. В VS2010 MVC2 может быть скомпилирован против .NET 3.5 или 4.0.
Производительность 3.5 хорошая и 4.0 плохо.
Я думаю, это означает, что плохо выполняющая часть не находится в сборке MVC, а в сборке фреймов (например, System.Web.Routing.dll). Вопрос все тот же: могу ли я что-то сделать? Принятый ответ также будет: Нет, код медленно, потому что, начиная с версии 3.5 до 4.0 MS изменили XXX
EDIT-2
Я декомпилировал часть System.Web.Routing.dll, которая длится долго. Он использует скомпилированное регулярное выражение. Существует путь к коду (constraint2.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);
}
Это происходит по первому запросу или в любое время? – dknaack
Первый запрос медленнее, время, которое я получил, является вторым запросом. И все это в режиме «выпуска». –
Просто из любопытства вы пробовали это без всех инструкций IgnoreRoute? – JTMon