Ich habe eine Anwendung, die ich kürzlich von ASP.NET MVC1 auf ASP.NET MVC4 rc1 aktualisiert.Leistung Engpass Url.Action - kann ich es umgehen?
Es verwendet die Webforms-Viewengine.
Es treten Leistungsprobleme auf, wenn Url.Action (Aktion, Controller) verwendet wird.
Ich kann das Problem in ASP.NET MVC3 reproduzieren.
Ich brauche 3ms, um Ansichten zu rendern, die 10 Instanzen des Url.Action-Helpers darin in ASP.NET MVC1 und 40 ms haben, um dasselbe in ASP.NET MVC3 zu rendern.
Ich fand schon einige Möglichkeiten, um es schneller machen:
ich die Standardroute nach oben
bewegtI entfernt Url.Action und verwendet statische Links
Das fühlt sich nicht richtig an: Die Anwendung ist ziemlich groß und ich brauche die Güte eines ordentlichen Arbeits-Routings darin. Ich bin auch nicht zuversichtlich, dass ich alle Leistungsengpässe gefunden habe. Routing ist ein zentraler Teil von MVC: Wenn etwas schlecht läuft, wird es in verschiedenen Teilen der Anwendung angezeigt.
Ich habe den Eindruck, dass MVC3 einige Routing-Funktionen (wie Regex-Einschränkungen) eingeführt hat, die, selbst wenn ich sie nicht verwende, zu einer schlecht durchführenden Anwendung führen.
Gibt es etwas, was ich tun kann, wie die Funktionen des Routing zu ändern oder einen anderen Satz von URL-Helfern zu verwenden?
Dieser Code reproduziert das Problem:
Index Aktion
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>
Strecke Registrierung Das sieht seltsam: aber ich will nur meine nicht sehr kompliziert simulieren Routing. Das sind nicht die 600 Routen von 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
Der Beispielcode wurde nun gegen MVC2 zusammengestellt. In VS2010 kann MVC2 gegen .NET 3.5 oder 4.0 kompiliert werden.
Die Leistung mit 3,5 ist gut und 4,0 ist schlecht.
Ich denke, das bedeutet, dass der schlecht funktionierende Teil nicht in einer MVC-Assembly, sondern in einer Framework-Assembly (wie System.Web.Routing.dll) ist. Die Frage ist immer noch die gleiche: Kann ich etwas dagegen tun? Eine akzeptierte Antwort wäre auch: Nein, das ist der Code langsam, da ab Version 3,5 bis 4,0 MS XXX
geändertEDIT-2
ich dekompilierten den Teil des System.Web.Routing.dll das dauert zu lange. Es verwendet einen kompilierten regulären Ausdruck. Es gibt einen Code-Pfad (constraint2.Match), der ohne Ausführung der Regex zurückkehrt, aber ich habe noch nicht überprüft, ob er intern eine andere teure Operation verwendet.
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);
}
Erfolgt dies auf die erste Anfrage oder jedes Mal? – dknaack
Die erste Anfrage ist langsamer, die Zeit, die ich gemessen habe, ist die zweite Anfrage. Und es ist alles im "Release" -Modus. –
Nur aus Neugier hast du es ohne alle IgnoreRoute Anweisungen versucht? – JTMon