Tengo una aplicación que actualicé recientemente de ASP.NET MVC1 a ASP.NET MVC4 rc1.Performance cuello de botella Url.Action - ¿puedo solucionarlo?
Utiliza Webforms viewengine.
Tiene problemas de rendimiento cuando se usa Url.Action (acción, controlador).
Puedo reproducir el problema en ASP.NET MVC3.
Necesito 3ms para renderizar vistas que tengan 10 instancias del ayudante Url.Action en ASP.NET MVC1 y 40ms para renderizar lo mismo en ASP.NET MVC3.
ya he encontrado algunas maneras de hacer que rinda más rápido:
I trasladó la ruta predeterminada a la parte superior
quité Url.Action y usados enlaces estáticos
Esto no se siente bien: la aplicación es bastante grande y necesito la bondad de una ruta de trabajo decente en ella. Tampoco estoy seguro de haber encontrado todos los cuellos de botella en el rendimiento. El enrutamiento es una parte central de MVC: si hay algo que funciona mal aparecerá en diferentes partes de la aplicación.
Tengo la impresión de que MVC3 introdujo algunas características de enrutamiento (como restricciones de expresiones regulares) que, incluso si no las utilizo, conducen a una aplicación que no funciona bien.
¿Hay algo que pueda hacer como cambiar las características del enrutamiento o utilizar un conjunto diferente de URL-helpers?
Este código reproduce el problema:
acción Índice
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>
Ruta de registro Esto parece extraño, pero sólo quiero para simular mi no es muy complicada enrutamiento ¡Estas no son las 600 rutas de 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" });
}
EDITAR
El código de ejemplo que fue compilada en MVC2 ahora. En VS2010 MVC2 se puede compilar contra .NET 3.5 o 4.0.
El rendimiento con 3.5 es bueno y 4.0 es malo.
Supongo que esto significa que la parte de bajo rendimiento no está en un ensamblado MVC sino en un ensamblado de estructura (como System.Web.Routing.dll). La pregunta sigue siendo la misma: ¿puedo hacer algo al respecto? Una respuesta aceptada también sería: No, el código es lenta porque a partir de la versión 3,5 a 4,0 MS cambió XXX
EDITAR-2
I decompiled parte de System.Web.Routing.dll que lleva mucho tiempo. Utiliza una expresión regular compilada. Hay una ruta de código (constraint2.Match) que se devuelve sin ejecutar la expresión regular, pero no comprueve aún si internamente utiliza una operación costosa diferente.
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);
}
¿Esto sucede en la primera solicitud o siempre? – dknaack
La primera solicitud es más lenta, el tiempo que mides es la segunda solicitud. Y todo está en modo "lanzamiento". –
¿Solo por curiosidad lo has probado sin todas las instrucciones de IgnoreRoute? – JTMon