测量调用 ASP.NET MVC 控制器操作的时间
Posted
技术标签:
【中文标题】测量调用 ASP.NET MVC 控制器操作的时间【英文标题】:Measure Time Invoking ASP.NET MVC Controller Actions 【发布时间】:2012-07-06 09:04:58 【问题描述】:MVC 4 应用程序的一些用户遇到了零星的缓慢。大概不是每个用户每次遇到这个问题时都会报告。
我的想法是测量每个控制器操作所花费的时间,并记录超过规定时间的操作调用的详细信息,以便于进一步分析(以排除或排除服务器/代码问题)。
有没有一种方便的方法来执行此类测量,这样我就可以避免在每个操作中添加检测代码?我目前没有在这个项目中使用 IOC,并且会犹豫是否为了解决这个问题而引入它。
有没有更好的方法来解决这类问题?
【问题讨论】:
【参考方案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
。请参阅我的更新答案。
提示:Stopwatch
有Restart
方法。
您也可以使用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。
【讨论】:
以上是关于测量调用 ASP.NET MVC 控制器操作的时间的主要内容,如果未能解决你的问题,请参考以下文章
使用 ASP.NET MVC 4 从控制器调用另一个不同的视图
ASP.NET MVC API 操作返回 404,所有其他操作都有效