15

ASP.NET MVC 的小基准测试。查看页面代码:

    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(() => 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")) ) %>

在具有 ASP.NET MVC Beta 的默认新项目模板上的典型 Core2 笔记本上运行此程序会产生以下结果:

38 毫秒,每个链接 0,038 毫秒

120 毫秒,每个链接 0.12 毫秒

54 毫秒,每个链接 0,054 毫秒

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

31 毫秒,每个链接 0,031 毫秒

112 毫秒,每个链接 0,112 毫秒

450 毫秒,每个链接 0.45 毫秒

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

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

Stack Overflow 应该由相同的框架提供支持,你们是如何解决这个扩展问题的?首页(大量链接)和预渲染控件的自由缓存?

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

4

4 回答 4

4

我在 MS 论坛上问了这个问题,得到了 MS MVC 开发人员的回答。

帖子

答案

从 MVC Preview 2 到昨天最近发布的 MVC Beta,路由发生了很多变化。其中一些更改包括性能改进。这里有一些技巧可以让您的应用程序中的 URL 生成更加高效:

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

  2. 将您最常用的路由放在路由表的开头。这将提高 URL 生成和处理传入 URL 的性能。路由工作基于第一场比赛获胜的规则。如果第一个匹配项是路由表中的第 100 个路由,那么这意味着它必须尝试 99 个其他路由并且没有一个匹配。

  3. 不要使用 URL 生成。有些人喜欢,有些人不喜欢。掌握起来有点棘手。如果您的 URL 非常动态,那么使用它会很好,但是当您开始的 URL 非常少并且您可能并不关心它们的外观时,它可能会有点麻烦。

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

于 2008-10-19T14:02:10.993 回答
1

好的,空白模板项目的两个额外指标:

<%= 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"}}))) %>

结果:

71 毫秒,每个链接 0,071 毫秒

35 毫秒,每个链接 0,035 毫秒

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

于 2008-10-17T14:15:11.467 回答
1

缓存链接可能对团队来说是一个很好的建议,因为它们在整个过程的生命周期内都不会改变(无论如何对于大多数应用程序来说)。

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

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

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

于 2008-10-17T13:58:01.503 回答
0

缓存链接可能对团队来说是一个很好的建议,因为它们在整个过程的生命周期内都不会改变(无论如何对于大多数应用程序来说)。

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

于 2008-10-17T17:43:58.630 回答