Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Page generation time - ASP.Net MVC

I'm looking for a way to track how long it took for a page to be generated by the server. I know I can use Trace to track this but I need a way to display this per page.

Its ASP.Net MVC 2

like image 458
LiamB Avatar asked Dec 01 '09 14:12

LiamB


3 Answers

You can implement it like a ActionFilterAttribute

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class LoggingAttribute : ActionFilterAttribute
{
    private readonly Stopwatch _sw;

    public LoggingAttribute()
    {
        _sw = new Stopwatch();
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _sw.Start();
        Debug.WriteLine("Beginning executing: " + GetControllerAndActionName(filterContext.ActionDescriptor));
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        _sw.Stop();
        var ms = _sw.ElapsedMilliseconds;

        Debug.WriteLine("Finishing executing: " + GetControllerAndActionName(filterContext.ActionDescriptor));
        Debug.WriteLine("Time elapsed: "+ TimeSpan.FromMilliseconds(ms).TotalSeconds);
    }

    private string GetControllerAndActionName(ActionDescriptor actionDescriptor)
    {
        return actionDescriptor.ControllerDescriptor.ControllerName + " - " + actionDescriptor.ActionName;
    }
}

Decorate every controller or action-method with it and voila, it spit outs the text in debug.

EDIT: If you want to print it on the page you could add this snippet to the OnActionExecuted method

if(filterContext.Result is ViewResult) { //Make sure the request is a ViewResult, ie. a page
  ((ViewResult) filterContext.Result).ViewData["ExecutionTime"] = ms; //Set the viewdata dictionary
}

Now you have the executiontime saved in ViewData and can access it in the page.. I usually put it in the masterpage like this

<!-- The page took <%= ViewData["ExecutionTime"] %> ms to execute -->
like image 115
Kenny Eliasson Avatar answered Nov 02 '22 00:11

Kenny Eliasson


Yep the Derin Suggestion is the standard Way to do it in an ASP.NEt application, i would just suggest add an if so it does not interfere with non-HTML responses: EDIT: added complete implementation

public class PerformanceMonitorModule : IHttpModule
{

    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += delegate(object sender, EventArgs e)
        {
            //Set Page Timer Star
            HttpContext requestContext = ((HttpApplication)sender).Context;
            Stopwatch timer = new Stopwatch();
            requestContext.Items["Timer"] = timer;
            timer.Start();
             };
        context.PostRequestHandlerExecute += delegate(object sender, EventArgs e)
        {

            HttpContext httpContext = ((HttpApplication)sender).Context;
            HttpResponse response = httpContext.Response;
            Stopwatch timer = (Stopwatch)httpContext.Items["Timer"];
            timer.Stop();

            // Don't interfere with non-HTML responses
            if (response.ContentType == "text/html")
            {
                double seconds = (double)timer.ElapsedTicks / Stopwatch.Frequency;
                string result_time = string.Format("{0:F4} sec ", seconds);
                RenderQueriesToResponse(response,result_time);
            }
        };
    }
    void RenderQueriesToResponse(HttpResponse response, string result_time)
    {
        response.Write("<div style=\"margin: 5px; background-color: #FFFF00\"");
        response.Write(string.Format("<b>Page Generated in "+ result_time));
        response.Write("</div>");
    }
    public void Dispose() { /* Not needed */ }
}

you can also add some style to it...

And remember to register your Module in WebConfig inside httpModules Section:

  <add name="Name" type="namespace, dll"/>

For a Complete Reference about this check the Pro ASP.NET MVC Framework by Steven Sanderson - Chapter 15 - Performance, Monitoring Page Generation Times.

EDIT:(comment @Pino) Here is the example for my project: alt text http://www.diarioplus.com/files/pictures/example_performance.JPG

like image 34
JOBG Avatar answered Nov 01 '22 22:11

JOBG


It will depend on where you want to include this information. For example you could write an http handler that will display the render time after the </html> tag:

public class RenderTimeModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, e) =>
        {
            var watch = new Stopwatch();
            var app = (HttpApplication)sender;
            app.Context.Items["Stopwatch"] = watch;
            watch.Start();
        };

        context.EndRequest += (sender, e) =>
        {
            var app = (HttpApplication)sender;
            var watch = (Stopwatch)app.Context.Items["Stopwatch"];
            watch.Stop();
            var ts = watch.Elapsed;
            string elapsedTime = String.Format("{0} ms", ts.TotalMilliseconds);
            app.Context.Response.Write(elapsedTime);
        };
    }

    public void Dispose()
    {
    }
}

If you want to display render time somewhere in the middle of the html page then this render time will not account for the total page render time.

like image 36
Darin Dimitrov Avatar answered Nov 01 '22 23:11

Darin Dimitrov