Mam aplikację, którą niedawno zaktualizowałem z ASP.NET MVC1 do ASP.NET MVC4 rc1.Zatkanie wydajności Url.Action - czy mogę go obejść?
Wykorzystuje widok technologii Webforms.
Ma problemy z wydajnością, gdy używany jest Url.Action (działanie, kontroler).
Mogę odtworzyć problem w ASP.NET MVC3.
Potrzebuję 3ms, aby renderować widoki, które mają 10 wystąpień pomocnika Url.Action w ASP.NET MVC1 i 40 ms, aby renderować to samo w ASP.NET MVC3.
już znaleźć kilka sposobów, aby to uczynić szybciej:
przeprowadziłem domyślną trasę na górę
usunąłem Url.Action i używane statyczne linki
To nie jest w porządku: aplikacja jest dość duża i potrzebuję dobrej jakości przyzwoitego routingu. Nie jestem również pewien, że znalazłem wszystkie wąskie gardła wydajności. Routing jest centralną częścią MVC: jeśli coś działa źle, pojawi się w różnych częściach aplikacji.
Mam wrażenie, że MVC3 wprowadził pewne funkcje routingu (takie jak ograniczenia regex), które nawet jeśli ich nie używam, prowadzą do źle działającej aplikacji.
Czy jest coś, co mogę zrobić, jak włączyć funkcje routingu lub korzystać z innego zestawu pomocników adresów URL?
Ten kod reprodukuje problem:
działanie Index
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>
Route rejestracja To wygląda dziwnie, lecz po prostu chcę symulować mój niezbyt skomplikowane routing. To nie jest 600 dróg 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
Kod próbki opracowano przeciwko MVC2 się. W VS2010 MVC2 można skompilować z .NET 3.5 lub 4.0.
Osiągi z 3.5 są dobre, a 4,0 złe.
Chyba oznacza to, że źle działająca część nie znajduje się w zespole MVC, ale w zespole szkieletowym (jak System.Web.Routing.dll). Pytanie wciąż jest takie samo: czy mogę coś z tym zrobić? Akceptowaną odpowiedź byłaby także: Nie, kod jest powolny, ponieważ od wersji 3.5 do 4.0 MS zmienił XXX
EDIT-2
I dekompilowana część System.Web.Routing.dll, która trwa długo. Używa skompilowanego wyrażenia regularnego. Istnieje ścieżka kodu (constraint2.Match), która zwraca się bez wykonywania regex, ale nie sprawdziłem jeszcze, czy wewnętrznie używa innej kosztownej operacji.
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);
}
Czy dzieje się to na pierwsze żądanie lub za każdym razem? – dknaack
Pierwsze żądanie jest wolniejsze, czas, o którym mówiono, jest drugim żądaniem. A wszystko to w trybie "wydania". –
Po prostu z ciekawości próbowaliście go bez wszystkich instrukcji IgnoreRoute? – JTMon