Note that there are some explanatory texts on larger screens.

plurals
  1. POPerformance bottleneck Url.Action - can I workaround it?
    primarykey
    data
    text
    <p>I have an application that I recently upgraded from ASP.NET MVC1 to ASP.NET MVC4 rc1.</p> <p>It uses the Webforms viewengine.</p> <p>It has performance issues whenever Url.Action(action,controller) is used.</p> <p>I can reproduce the issue in ASP.NET MVC3.</p> <p>I need 3ms to render views that have 10 instances of the Url.Action helper in it in ASP.NET MVC1 and 40ms to render the same in ASP.NET MVC3. </p> <p>I already found some ways to make it render faster:</p> <ul> <li><p>I moved the default route to the top</p></li> <li><p>I removed Url.Action and used static links</p></li> </ul> <p>This does not feel right: the application is pretty large and I need the goodness of a decent working routing in it. I am also not confident that I found all performance bottlenecks. Routing is a central part of MVC: if there is something performing badly it will pop up in different parts of the application.</p> <p>I have the impression that MVC3 introduced some routing features (like regex constraints) that even if I dont use them lead to a badly performing application.</p> <p>Is there something I can do like turning of features of routing or using a different set of URL-helpers?</p> <p>This code reproduces the issue:</p> <p>Index action</p> <pre><code>public ActionResult Index() { return View(); } </code></pre> <p>index.aspx</p> <pre><code>&lt;%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %&gt; &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt; &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt; &lt;head &gt; &lt;title&gt;&lt;/title&gt; &lt;link href="../../Content/Site.css" rel="stylesheet" type="text/css" /&gt; &lt;/head&gt; &lt;body&gt; &lt;div class="page"&gt; &lt;%= Url.Action("Action1", "Controller1") %&gt; &lt;%= Url.Action("Action2", "Controller2") %&gt; &lt;%= Url.Action("Action3", "Controller3") %&gt; &lt;%= Url.Action("Action4", "Controller4") %&gt; &lt;%= Url.Action("Action5", "Controller5") %&gt; &lt;%= Url.Action("Action6", "Controller6") %&gt; &lt;%= Url.Action("Action7", "Controller7") %&gt; &lt;%= Url.Action("Action8", "Controller8") %&gt; &lt;%= Url.Action("Action9", "Controller9") %&gt; &lt;%= Url.Action("Action10", "Controller10") %&gt; &lt;/div&gt; &lt;/body&gt; &lt;/html&gt; </code></pre> <p>Route registration This looks strange: but I just want to simulate my not very complicated routing. This is not the 600 routes of SO!</p> <pre><code>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 &lt;= 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" }); } </code></pre> <p><strong>EDIT</strong></p> <p>The sample code was compiled against MVC2 now. In VS2010 MVC2 can be compiled against .NET 3.5 or 4.0.</p> <p>The performance with 3.5 is good and 4.0 is bad. </p> <p>I guess this means that the poorly performing part is not in a MVC assembly but in a framework assembly (like System.Web.Routing.dll). The question is still the same: Can I do something about it? An accepted answer would also be: No, the code is slow because from version 3.5 to 4.0 MS changed XXX</p> <p><strong>EDIT-2</strong></p> <p>I decompiled the part of System.Web.Routing.dll that takes to long. It uses a compiled regular expression. There is a code path (constraint2.Match ) that returns without executing the regex, but I did not check yet if it internally uses a different expensive operation.</p> <pre><code>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); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload