forge

Capturing Page Load Times – FiddlerScript to the Rescue

So I have a client who has locations all over the world and we’ve been doing some analysis of some performance issues with SharePoint.  We believe that we narrowed down the issue to SQL server not having enough memory.  The key indicator for SQL Server memory is SQL Server Buffer Manager: Page Life Expectancy (PLE) – anything less than 300 (seconds) isn’t going to perform optimally.  However, we needed some “proof” that changing the SQL memory changed the performance – for people across the world.  The solution, rather than buying and setting up expensive monitoring all over the world was to get some of the users to run Fiddler.  If you’ve never seen the tool you should go check it out now.  (You can go look at an article I wrote in 2006 if you want to see what I was thinking 4 years ago.)

The problem was that there’s no quick and simple way to get the session timers out of Fiddler.  That is except that Eric Lawrence (the author of Fiddler) is a genius.  He added scripting support to Fiddler so you can script the stuff you need.  With a few looks at the cookbook, some trial and error, and a few pointers from Eric, I wrote some script that creates a tab separated value file which can be imported into Excel.  The file has all of the key timers and the number of milliseconds that elapsed.  You can go to Rules-Customize Rules (Ctrl-R) to customize the rules – or you can download the handy script editor.  I added a tools menu option to write all of the session timers to a TSV and a context menu option to write the selected session timers to a TSV.  The code is below if you want to do this yourself.  By the way, I used a tab separated value file because I had a situation where some of my URLs had commas in them.  (Don’t ask)  I won’t guarantee this is the absolute best way to make this all work – but it’s functional.

Help Your SharePoint User

public static ToolsAction(“Write all session timers to TSV file”)
function WriteAllSessionTimers()
{
       var fileName = GetSaveFileName();
       if (fileName != null)
       {
              var oSessions : Fiddler.Session[] = FiddlerApplication.UI.GetAllSessions();
              WriteSelectedSessionTimersToFileName(oSessions, fileName);
       }

}

public
static ContextAction(“Write selected session timers to TSV file”)
function WriteSelectedSessionTimers(oSessions: Fiddler.Session[])
{
       var fileName = GetSaveFileName();
       if (fileName != null)
       {
              WriteSelectedSessionTimersToFileName(oSessions, fileName);
       }
}

public
static function GetSaveFileName()
{
       var sfd : System.Windows.Forms.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();

sfd.Filter = “Tab Separated Value (*.tsv)|*.tsv|All files (*.*)|*.*”;
       if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
       {
              return(sfd.FileName);
       }
       else return (null);
}

public static function WriteSelectedSessionTimersToFileName(oSessions: Fiddler.Session[], filename: System.String)
{
       try
{

if
(oSessions == null || oSessions.Length == 0)
              {
                     MessageBox.Show(“Please select sessions first”, “Warning”);
                     return;
              }

var
sb: System.Text.StringBuilder = new System.Text.StringBuilder();
       sb.Append(“Host\tPathAndQuery\tMimeType\tClientConnected\tClientDoneRequest\tServerConnected\tServerGotRequest\tServerBeginResponse\tServerDoneResponse\tClientBeginResponse\tClientDoneResponse\tTotalTimeMS\r\n”);
              for (var looper=0; looper<oSessions.Length; looper++)
              {
                     var ts: System.TimeSpan = null;
                     var dtStart: DateTime = oSessions[looper].Timers.ClientConnected;
                     var dtEnd: DateTime = oSessions[looper].Timers.ClientDoneResponse;
                     ts = dtEnd dtStart;
                     var mimeType = null;
                     if (oSessions[looper].oResponse.headers.Exists(“Content-Type”))
                     {
                           mimeType = oSessions[looper].oResponse.headers[“Content-Type”];
                           if (mimeType.indexOf(‘;’) > 1) mimeType = mimeType.substr(0, mimeType.indexOf(‘;’));
                     }

sb.Append(oSessions[looper].host).Append(‘\t’)
                           .Append(oSessions[looper].PathAndQuery).Append(‘\t’)
                           .Append(mimeType).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ClientConnected.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ClientDoneRequest.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ServerConnected.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ServerGotRequest.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ServerBeginResponse.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ServerDoneResponse.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ClientBeginResponse.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(oSessions[looper].Timers.ClientDoneResponse.ToString(“MM/dd/yyyy h:mm:ss.ffff )).Append(‘\t’)
                           .Append(ts.TotalMilliseconds).Append(“\r\n”);
              }

var
sw : System.IO.StreamWriter = System.IO.File.CreateText(filename);
              sw.Write(sb.ToString());
              sw.Close();
              sw.Dispose();
       }
       catch (excpt: System.Exception)
       {
              MessageBox.Show(excpt.ToString());
       }
}

 

1 reply
  1. Sid
    Sid says:

    Hi,

    When I try this script it brings down my network card. Any suggestions for what I am doing wrong.

Comments are closed.