Ho un'applicazione che ho recentemente aggiornato da ASP.NET MVC1 a ASP.NET MVC4 rc1.Bottleneck delle prestazioni Url.Action: posso aggirarlo?
Utilizza il motore di visualizzazione Webform.
Ha problemi di prestazioni ogni volta che si utilizza Url.Action (azione, controller).
Posso riprodurre il problema in ASP.NET MVC3.
Ho bisogno di 3 ms per eseguire il rendering di 10 istanze dell'heler Url.Action in esso in ASP.NET MVC1 e 40 ms per il rendering dello stesso in ASP.NET MVC3.
ho già trovato alcuni modi per rendere rendere più veloce:
ho spostato il percorso di default in cima
ho rimosso e utilizzato Url.Action collegamenti statici
Questo non mi sembra giusto: l'applicazione è abbastanza grande e ho bisogno della bontà di un instradamento funzionante decente. Non sono nemmeno sicuro di aver trovato tutti i colli di bottiglia delle prestazioni. Il routing è una parte centrale di MVC: se c'è qualcosa che si comporta male comparirà in diverse parti dell'applicazione.
Ho l'impressione che MVC3 abbia introdotto alcune caratteristiche di routing (come i vincoli di regex) che anche se non le uso, portano a un'applicazione mal funzionante.
C'è qualcosa che posso fare come la disattivazione delle funzionalità di routing o l'uso di un diverso set di URL-helpers?
Questo codice riproduce il problema:
azione Indice
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>
percorso di registrazione Questo sembra strano: ma voglio solo simulare il mio non è molto complicato routing. Questo non è il 600 percorsi di 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
Il codice di esempio è stato compilato contro MVC2 ora. In VS2010 MVC2 può essere compilato con .NET 3.5 o 4.0.
Le prestazioni con 3.5 sono buone e 4,0 non sono buone.
Immagino che questo significhi che la parte con prestazioni scadenti non si trova in un assieme MVC ma in un assieme quadro (come System.Web.Routing.dll). La domanda è sempre la stessa: posso fare qualcosa al riguardo? Una risposta accettata sarebbe anche: No, il codice è lento perché dalla versione 3,5-4,0 MS cambiato XXX
EDIT-2
Ho decompilato la parte di System.Web.Routing.dll che dura a lungo. Usa un'espressione regolare compilata. Esiste un percorso di codice (constraint2.Match) che ritorna senza eseguire la regex, ma non ho ancora controllato se utilizza internamente un'operazione costosa diversa.
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);
}
Questo succede alla prima richiesta o sempre? – dknaack
La prima richiesta è più lenta, il tempo che ho misurato è la seconda richiesta. Ed è tutto in modalità "rilascio". –
Solo per curiosità l'hai provato senza tutte le istruzioni di IgnoreRoute? – JTMon