【问题标题】:Measure Time Invoking ASP.NET MVC Controller Actions测量调用 ASP.NET MVC 控制器操作的时间
【发布时间】:2012-07-06 09:04:58
【问题描述】:

MVC 4 应用程序的一些用户遇到了零星的缓慢。大概不是每个用户每次遇到这个问题时都会报告。

我的想法是测量每个控制器操作所花费的时间,并记录超过规定时间的操作调用的详细信息,以便于进一步分析(以排除或排除服务器/代码问题)。

有没有一种方便的方法来执行此类测量,这样我就可以避免在每个操作中添加检测代码?我目前没有在这个项目中使用 IOC,并且会犹豫是否为了解决这个问题而引入它。

有没有更好的方法来解决这类问题?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 asp.net-mvc-5


    【解决方案1】:

    您能创建一个全局操作过滤器吗?像这样的:

    public class PerformanceTestFilter : IActionFilter
    {
        private Stopwatch stopWatch = new Stopwatch();
    
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            stopWatch.Reset();
            stopWatch.Start();
        }
    
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            stopWatch.Stop();
            var executionTime = stopWatch.ElapsedMilliseconds;
            // Do something with the executionTime
        }
    }
    

    然后将其添加到您在 `Application_Start()' 中的 GlobalFilters 集合中

    GlobalFilters.Filters.Add(new PerformanceTestFilter());
    

    您可以从filterContext 参数中获取有关正在测试的控制器的详细信息。

    更新

    将过滤器直接添加到GlobalFilters 集合将为所有操作创建一个过滤器实例。当然,这不适用于定时并发请求。要为每个操作创建一个新实例,请创建一个过滤器提供程序:

    public class PerformanceTestFilterProvider : IFilterProvider
    {
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            return new[] {new Filter(new PerformanceTestFilter(), FilterScope.Global, 0)};
        }
    }
    

    那么与其直接添加过滤器,不如在Application_Start()中添加过滤器提供者:

    FilterProviders.Providers.Add(new PerformanceTestFilterProvider());
    

    【讨论】:

    • 听起来很有希望。我会试一试。为我假设的每个操作创建一个 PerformanceTestFilter 实例(以便它拥有自己的 Stopwatch 实例)?
    • 其实......它没有。您需要为此创建一个IFilterProvider。请参阅我的更新答案。
    • 提示:StopwatchRestart 方法。
    • 您也可以使用filterContext.HttpContext.Items 来存储您的秒表并在之后取回(以及actionContext.Request.Properties 用于WebApi 过滤器)。
    • 不存在竞争条件吗?如果多个请求使用同一个过滤器实例bradwilson.typepad.com/blog/2010/07/…
    【解决方案2】:

    更新 - 使用 Install-Package StopWatch 安装我的 Stopwatch NuGet 包 见Profile and Time your ASP.NET MVC app all the way to Azure

    看我的教程Using Asynchronous Methods in ASP.NET MVC 4 它有一个全局动作过滤器计时器。您可以使用 ELMAH 来记录数据。我的示例 我的示例http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98) 也具有相同的定时过滤器,并且更简单,但它是 Razor 之前的版本。

    查找秒表属性以启用计时。

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new UseStopwatchAttribute());
        }
    }
    

    【讨论】:

    • 我在教程中找不到全局操作过滤器。尝试搜索“全局”、“过滤器”和“计时器”,但均未命中。
    • 在我的答案中添加了全局过滤器
    【解决方案3】:

    试试ASP.NET 4.5 Page Instrumentation

    它检测页面渲染:您的应用程序的时间可能花费在控制器中,但有很多时间花费在视图渲染中。特别是如果你有很多部分和 html 帮助器。

    【讨论】:

      【解决方案4】:

      我通常将这个简单的代码添加到布局视图的底部:

      <!-- Page generated in @((DateTime.UtcNow - HttpContext.Current.Timestamp.ToUniversalTime()).TotalSeconds.ToString("F4")) s -->
      

      输出类似:

      <!-- Page generated in 0.4399 s -->
      

      这开始测量HttpContext 的创建时间(根据the documentation),并在写入输出之前停止,因此它应该非常准确。

      它可能不适用于所有用例(如果您想测量子操作,或忽略 MVC 操作之外的时间等),但它很容易粘贴到视图中。

      对于更高级的诊断,我曾经使用Glimpse

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-12
        相关资源
        最近更新 更多