问题
I've built a JSON service in ASP.NET MVC 3 and I want to be able to measure the execution time of the actions in my application (I want to it to automatically log slow actions).
Therefor this looked great; http://coderjournal.com/2010/10/timing-the-execution-time-of-your-mvc-actions/ (It's been mentioned on places here on stack overflow as well)
The problem is that I get measurements that MUST be wrong from this method; I've added another stopwatch that starts the first thing in the action and stops just before the return.
Example:
- Stopwatch inside the method => 10ms (the serializing to json is omitted here, so I can understand that it's shorter than reality)
- Stopwatch attribute (code above) => 676ms
- Firefox says the request took => 70ms .
I believe that firefox has the correct time here (but it includes the download so it's a bit large), but I want to understand why the attribute code doesn't work, any ideas for this?
回答1:
This might not be the reason why it shows that long execution time, but that attribute won't work correctly with mvc 3 when you have multiple requests at once.
In previous versions of ASP.NET MVC, action filters are create per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.
I'd recommend to instantiate new stopwatch in OnActionExecuting
and save it to HttpContext.Current.Items - then you can retrieve it in OnActionExecuted
and print out result.
回答2:
More correct approach in addition to answer https://stackoverflow.com/a/5823555/504082 is to use OnResultExecuted override at the end of clock execution. When you return
ActionResponse.Success(arr.Select(x => func(x)).ToJson();
i.e. some lazy LINQ statement as a result of your action, it will be calculated after action is "executed" (function 'func' execution will not be count towards action execution time). I've got this nasty bug and couldn't figure out why my action "execution time" is 100 ms although web request executes 10 seconds. Modified code below.
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());
}
}
}
回答3:
Why not have a look at page performance module from Rhino commons?
回答4:
Looks like you are off by an order of magnitude. Are you sure you are reading the result correctly? Try using the Stopwatch.ElapsedMilliseconds property.
来源:https://stackoverflow.com/questions/5821411/measuring-performance-of-asp-net-mvc-3