ASP.NET MVC 3性能测量

11

我在ASP.NET MVC 3中构建了一个JSON服务,想要测量我的应用程序中操作的执行时间(我希望它能自动记录慢操作)。

因此,这看起来很不错:http://coderjournal.com/2010/10/timing-the-execution-time-of-your-mvc-actions/ (它也在stackoverflow的其他地方被提到过)

问题是我从这种方法得到的测量值一定是错误的;我添加了另一个秒表,在操作中的第一件事情开始计时,在返回之前停止计时。

例如:

  • 方法内的秒表 => 10ms (这里省略了将数据序列化为json的过程,所以我可以理解它比现实短)
  • 属性中的秒表(上面的代码) => 676ms
  • Firefox显示请求时间 => 70ms

我相信Firefox的时间是正确的(但它包括下载,所以有点大),但我想了解为什么属性代码不起作用,对此有什么想法吗?


是的,在Firefox中缓存已关闭... - ullmark
4个回答

16

这可能不是导致执行时间过长的原因,但当您有多个请求时,该属性在mvc 3中将无法正常工作。

在之前的ASP.NET MVC版本中, 操作筛选器是每个请求创建一次 除了一些例外情况。这种行为 从未是一种保证的行为,而只是 实现细节和筛选器的合同是 将其视为无状态的。在ASP.NET MVC 3中,筛选器会更积极地缓存。 因此,任何不正确存储实例状态的自定义 操作筛选器可能会出错。

我建议在OnActionExecuting中实例化新的秒表并将其保存到HttpContext.Current.Items - 然后您可以在OnActionExecuted中检索它并打印结果。


你是正确的,因为这些操作被缓存了,构造函数只会偶尔运行一次,所以同一个秒表会被重复使用。 - ullmark
1
有关的代码已经更新,现在按照Lukáš Novotný的建议运行。 - Fernando Correia
这不会返回可靠的结果,因为视图在呈现后可能会调用ChildActions。 - MichaelD

8

除了答案https://dev59.com/MW025IYBdhLWcg3wvIu2#5823555之外,更正确的方法是在时钟执行结束时使用OnResultExecuted重写。

当你返回时

ActionResponse.Success(arr.Select(x => func(x)).ToJson();

例如,由于您的操作而产生的某些懒惰的LINQ语句将在操作“执行”之后计算(函数'func'的执行不会计入操作执行时间)。 我遇到了这个讨厌的错误,无法弄清楚为什么我的操作“执行时间”是100毫秒,尽管Web请求执行了10秒。修改后的代码如下。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace SW
{
    public class StopwatchAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var stopwatch = new Stopwatch();
            filterContext.HttpContext.Items["Stopwatch"] = stopwatch;

            stopwatch.Start();
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            var stopwatch = (Stopwatch)filterContext.HttpContext.Items["Stopwatch"];
            stopwatch.Stop();

            var httpContext = filterContext.HttpContext;
            var response = httpContext.Response;

            response.AddHeader("X-Runtime", stopwatch.Elapsed.TotalMilliseconds.ToString());
        }
    }
}

这太棒了。你知道是否可能将其与“ActionFilterAttribute”分离,以便可以用于任何方法吗?我想我只需要为属性添加一个名称属性来跟踪各种秒表或记录并在EndRequest时停止它,但我无法弄清楚如何获取非操作的"OnResultExecuted"事件。 - Joel Peltonen
如果你想在网页中有一个“调试”控制台,这就非常好。 - Kat Lim Ruiz

1

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接