views:

759

answers:

3

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?

A: 

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 ...
   }
}
tvanfosson
A: 

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
    }
}
David Brown
I think this will only give you the time to set up the result data, not actually render the page. For rendering time, the OnResultExecuted, which is invoked after the ActionResult has been executed is more accurate.
tvanfosson
True, but I don't think you can modify the ViewData once the result has been executed, which means there's no way to display the execution time on the page. Correct me if I'm wrong, though.
David Brown
Yes. That would be my understanding, too. But you could store the time and retrieve it via AJAX if you needed to get an accurate measure. Personally I would log it and not worry about getting it on the page itself.
tvanfosson
+3  A: 

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);
Chad Moran
Thanks... I would really like to see the page render time on the footer of the master page.
TonyAbell
You can use the Trace object and do Trace.Write() to write to the trace output and it will add it in the list of events and render times etc.
Chad Moran