Page Render Time in MVC

2019-03-15 23:47发布

问题:

Q: How do I calculate the total time it takes to render an MVC page and display the time on the master page.

In Asp.net Web Form I created a Base page class like so:

public class PageBase : System.Web.UI.Page
{      
    private DateTime startTime = DateTime.Now;
    private TimeSpan renderTime;   
    public DateTime StartTime
    {
        set { startTime = value; }
        get { return startTime; }
    }  
    public virtual string PageRenderTime
    {
        get
        {
            renderTime = DateTime.Now - startTime;
            return renderTime.Seconds + "." + renderTime.Milliseconds + " seconds";
        }
    }       
}

I would then call the method on my Master Page like so:

<div id="performance">
     <% =PageRenderTime %>
</div>

Q: How do I accomplish the same thing with the MVC Framework?

Q: With the MVC framework where do I set the start time when a page is first created?

回答1:

The best way to do this is calculate the request timing .. Begin Request and End Request .... Check out this great post:

http://haacked.com/archive/2008/07/02/httpmodule-for-timing-requests.aspx



回答2:

Go into your web.config and make sure you have...

<system.web>
    <trace enabled="true" localOnly="false" />
</system.web>

Then you can goto http://.../trace.axd and see every request made.

Then you want to look under the From First(s) column and the very last one is the time it took to render the page (server side).

Example...

aspx.page   End Render  0.06121112  0.005297

61.2 ms to render the page.

If you're looking to time code itself or you want to manually do some diagnostics you want to use the System.Diagnostics.Stopwatch class not DateTime.

Stopwatch sw = Stopwatch.StartNew();
...
sw.Stop();
Trace.Write(sw.ElapsedMilliseconds);


回答3:

I would probably override the OnActionExecuting and OnActionExecuted methods on the Controller class.

public class BaseController : Controller {
    // Called before the action is executed
    public override void OnActionExecuting(ActionExecutingContext ctx) {
        base.OnActionExecuting(ctx);
        // Start timing
    }

    // Called after the action is executed
    public override void OnActionExecuted(ActionExecutedContext ctx) {
        base.OnActionExecuted(ctx);
        // Stop timing
    }
}


回答4:

Create a base controller and have your controllers derive from it. Set your start time in the constructor and override Dispose() and put the calculation of the total time there. This should give you an end-to-end on the entire life of the action. Since Controller implements IDisposable, I'm assuming that the render engine will dispose it after the result is computed and you won't have to wait for garbage collection. If my assumption turns out to be wrong, you could use OnResultExecuted() instead.

EDIT: To get the rendering time on the page would be relatively hard because by definition the page can't be done rendering until your time is put on the page and you can't have the time until the page is done rendering. You could, however, write the render time to the session then use AJAX to come back and get the render time for display later. You might be able to approximate it by putting the start time in ViewData and calculating the rendering time in the View itself. You might want to try logging the render time and doing the view approximation and see how close it is.

This code could be used to log the render time.

public class BaseController : Controller
{
   private DateTime StartTime { get; set; }
   public BaseController() : base()
   {
       StartTime = DateTime.Now;
   }

   public override void Dispose( bool disposing )
   {
       var totalTime = DateTime.Now - this.StartTime;
       ... write it out somewhere ...
   }
}