C# ASP.NET MVC URL生成性能

C# ASP.NET MVC URL生成性能,c#,performance,asp.net-mvc-routing,C#,Performance,Asp.net Mvc Routing,一个ASP.NETMVC的小基准。查看页面代码: public string Bechmark(Func<string> url) { var s = new Stopwatch(); var n = 1000; s.Reset(); s.Start(); for (int i = 0; i < n; i++) { var u = url()

一个ASP.NETMVC的小基准。查看页面代码:

    public string Bechmark(Func<string> url)
    {
        var s = new Stopwatch();
        var n = 1000;

        s.Reset();
        s.Start();
        for (int i = 0; i < n; i++)
        {
            var u = url();
        }
        s.Stop();
        return s.ElapsedMilliseconds + " ms, " + ((s.ElapsedMilliseconds) / (float)n) + " ms per link<br/>";
    }
公共字符串Bechmark(Func url)
{
var s=新秒表();
var n=1000;
s、 重置();
s、 Start();
对于(int i=0;i”;
}
查看代码:

<%= Bechmark(() => Url.Action("Login", "Account")) %>

<%= Bechmark(() => Url.Action("Login", "Account", new {username="bla", password="bla2", returnurl="blabla32", rememberme=false} )) %>

<%= Bechmark(() => Html.BuildUrlFromExpression<AccountController>(a=>a.ChangePassword("bla", "bla", "ya")) ) %>
Url.Action(“登录”、“帐户”))%>
Action(“Login”,“Account”,new{username=“bla”,password=“bla2”,returnurl=“blabla32”,rememberme=false}))%>
Html.BuildUrlFromExpression(a=>a.ChangePassword(“bla”、“bla”、“ya”))%%>
在ASP.NET MVC Beta版的默认新项目模板上,在典型的Core2笔记本电脑上运行此操作,将产生以下结果:

38毫秒,每条链路0.038毫秒

120毫秒,每个链路0,12毫秒

54毫秒,每条链路0054毫秒

在一个生产项目上运行相同的基准测试时,大约有10个控制器,其中包含大约100个方法和30个路由表条目,基于表达式的方法的性能会大大降低:

31毫秒,每条链路0.031毫秒

每个链路112毫秒,0112毫秒

450毫秒,每个链路0,45毫秒

我们经常使用这种方法(可维护性)并进行一些性能基准测试,这会大大降低站点的性能-页面很快包含30个或更多这样的链接,这意味着单个页面上会增加10毫秒的额外开销。即使是每个URL 0.112ms,纯CPU开销也只有4ms左右

应该注意的是,MVC Preview 3和Beta(昨天发布)之间的所有三个URL生成调用的性能都提高了5倍

堆栈溢出被认为是由同一个框架驱动的,你们是如何解决这个扩展问题的?首页(大量链接)和预呈现控件的自由缓存


ASP.NET MVC中的任何其他生产网站是否存在性能问题或一些好的提示?

缓存链接可能是团队的一个好建议,因为它们在整个过程中不会改变(无论如何,对于大多数应用程序)

在您开始以可配置的形式(如web.config或数据库)定义路由之前,您必须稍微缩小一点

我怀疑中间示例的延迟很大一部分是自动转换为字典的匿名类型。缓存URL在这里没有任何帮助b/c您仍然需要反映该类型


同时,您可以为一些基于字典的链接创建自己的帮助器方法,这些链接会获取您所需的确切输入。然后,您可以自己处理缓存。

< P> OK,空白模板项目上的两个附加度量:

<%= Bechmark(() => Url.Action("Login", "Account", new Dictionary<string, object> {{"username", "bla"}, {"password", "bla2"}, {"returnurl", "blabla32"}, {"rememberme", "false"}})) %>

<%= Bechmark(() => Url.Action("Login", "Account", new RouteValueDictionary(new Dictionary<string, object> {{"username", "bla"}, {"password", "bla2"}, {"returnurl", "blabla32"}, {"rememberme", "false"}}))) %>
Url.Action(“Login”、“Account”、新字典{{{“username”、“bla”}、{“password”、“bla2”}、{“returnurl”、“blablabla32”}、{“rememberme”、“false”}))%>
Action(“Login”,“Account”,newRouteValueDictionary(newDictionary{{“username”,“bla”},{“password”,“bla2”},{“returnurl”,“blablabla32”},{“rememberme”,“false”})))%>
结果:

71毫秒,每条链路0071毫秒

35毫秒,每条链路0.035毫秒

使用更糟糕的代码可以获得更好的性能。太糟糕了


缓存链接可能是一个好方法 对团队的建议,因为他们不会 过程生命周期的变化 (无论如何,对于大多数应用程序)


你如何缓存链接,据我所知,你不能这样做,因为你需要缓存执行的方法,这发生在路由解析之后,这是缓慢的部分。

我在MS论坛上问了这个问题,一位MS MVC开发人员回答了这个问题

答案

从MVC预览版2到昨天发布的MVC测试版,路由有很多变化。其中一些变化包括性能改进。以下是一些使URL生成在应用程序中更高效的技巧:

  • 使用命名路由。命名路由是路由的可选功能。这些名称仅适用于URL生成-它们从不用于匹配传入URL。当您在生成URL时指定名称时,我们将仅尝试匹配该一个路由。这意味着,即使指定的命名路由是路由表中的第100条路由,我们也会直接跳到它并尝试匹配

  • 将最常见的路线放在路线表的开头。这将提高URL生成和处理传入URL的性能。路由根据第一场比赛获胜的规则工作。如果第一个匹配是路由表中的第100条路由,那么这意味着它必须尝试99条其他路由,但没有一条匹配

  • 不要使用URL生成。有些人喜欢,有些人不喜欢。这有点难掌握。如果你的URL是非常动态的,那么使用它是很好的,但是如果你一开始只有很少的URL,并且可能你并不关心它们到底是什么样子,那么这可能会有点麻烦

  • 我最喜欢的选项是#1,因为它非常易于使用,而且从应用程序开发人员的角度(就是你!)来看,它还使URL生成更具确定性


    问题:如果您仍然关心,请使用命名路由:在您的global.asax中,您使用routes.MapRoute(“routeName”,yadiyadiya);然后在您的操作中,您可以执行重定向路由(“routeName”,viewData);在某个地方可能会有更多这样的链接:@Nik:事实上,我是该演示文稿的作者,所以。。。是。:)有人知道ASP.NET MVC2是否仍然存在此问题吗?