8

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

    bewegt
  • I 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ändert

EDIT-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); 
} 
+0

Erfolgt dies auf die erste Anfrage oder jedes Mal? – dknaack

+0

Die erste Anfrage ist langsamer, die Zeit, die ich gemessen habe, ist die zweite Anfrage. Und es ist alles im "Release" -Modus. –

+0

Nur aus Neugier hast du es ohne alle IgnoreRoute Anweisungen versucht? – JTMon

Antwort

3

Es gibt ein ähnliches Problem wie Ihres: First call to Url.Action on a page is slow Es gibt Schlussfolgerungen über Routing-Einschränkungen mit Regexp-Einschränkungen, die sehr langsam sind.

+0

Mit meiner eigenen Implementierung von IRouteConstraint wie in der angenommenen Antwort beschrieben, löste das Problem. –

0

Jede Ansicht wird kompiliert und zwischengespeichert, wenn sie das erste Mal verwendet wird. Da die aspx-Ansichten jedoch nicht speziell für Mvc entworfen wurden, wird jede URL-Aktion im letzten Link nicht ein für allemal kompiliert, sondern bei jeder Ausführung neu berechnet. Razor Compiler hat eine bessere Optimierung. Die einzige Lösung besteht darin, die verschiedenen Verknüpfungen mit Url.Action zu berechnen und sie in einer Eigenschaft auf Anwendungsebene zu speichern, sodass sie nur bei der ersten Ausführung berechnet wird. Sie können sie entweder in das Anwendungswörterbuch oder in statische Eigenschaften einer Klasse einfügen.

0

Ich bin mir nicht sicher, was Sie sehen, aber es kann nicht nur eine MVC 1 vs MVC 4, IIS-Setup in späteren Versionen kann die Geschwindigkeit der Ansicht Rendering auswirken. Ich bin vor ein paar Monaten auf einen Diaprojektor gestoßen, den ich für ziemlich interessant hielt, in Bezug auf Tipps zur Leistungsverbesserung in MVC 3-Apps.

http://www.slideshare.net/ardalis/improving-aspnet-mvc-application-performance

Insbesondere werfen Sie einen Blick auf Schlitten 28, in dem es heißt:

Deinstallieren IIS UrlRewrite Modul

  • Wenn keine Anwendungen auf dem Server sind es
  • mit
  • Kein Effekt in MVC-Anwendungen vor v3
  • Verstärkt Geschwindigkeit der URL Generation

ich das so verstehen, dass die UrlRewrite Modul MVC negativ auswirken 3, aber nicht MVC 2 oder 1, die eine Quelle der Verlangsamung sein könnte, die Sie sehen. Es gibt noch einige andere Verbesserungen, aber ich glaube nicht, dass sich irgendwelche von ihnen direkt auf das beziehen, was Sie sehen.