RSS

Releasing WebPerfTest Tool

March 11th, 2008 Posted in Utilities, Web Site

I posted a while back in the article StartLogic: Day Three that I had written a little program to test the performance of my web site on a previous web host I was using. I’m releasing this application along with the source code under the GNU GPL license.

Here’s a brief rundown of what the code is doing. I created a PerfTimer class that is used to time how long it takes to get a response back. It calls the Win32 API performance timer calls to get accurate timing information.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    public class PerfTimer
    {
        private long startTime;
        static private readonly long frequency;
 
        // P/Invokes for Win32 performance counter functions
        [DllImport("kernel32.dll")]
        extern static int QueryPerformanceCounter(ref long val);
 
        [DllImport("kernel32.dll")]
        extern static int QueryPerformanceFrequency(ref long val);
 
        // Static contructor called once when the program starts. The frequency is
        // constant so we only need to get it once.
        static PerfTimer()
        {
            QueryPerformanceFrequency(ref frequency);
        }
 
        // Start the timer when the object is constructed
        public PerfTimer()
        {
            Start();
        }
 
        // Start the timer
        public void Start()
        {
            QueryPerformanceCounter(ref startTime);
        }
 
        // Get the time in seconds
        public double Time()
        {
            long time = 0;
            QueryPerformanceCounter(ref time);
 
            return (double)(time - startTime) / (double)frequency;
        }
    }

The QueryPerformanceFrequency function gives the number of counts per second for the counter value given by calling QueryPerformanceCounter. These values are 64 bit integers so you have to use the long data type. To get the number of seconds you simply subtract the end time from the start time and divide by the frequency.

Configuration information is loaded from the application config file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    <configSections>
        <section name="urls" type="System.Configuration.NameValueSectionHandler" />
    </configSections>
 
    <appSettings>
        <!-- Number of milliseconds to wait between tests. 15000 minimum -->
        <add key="SleepMilliseconds" value="60000"/>
 
        <!-- HTML output file name-->
        <add key="HtmlFileName" value="c:\WebPerf.html"/>
    </appSettings>
 
    <!-- URL test list -->
    <urls>
        <add key="TrailsInTheSand" value="http://trailsinthesand.com" />
        <add key="Slashdot" value="http://slashdot.org" />
    </urls>

The URLs are loaded from a custom configuration section named urls. Since they are just names and values we can use the NameValueSectionHandler so we don’t have to write custom code to retreive the data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        // Load configuration information
        static void LoadConfig()
        {
            sleepMilliseconds = int.Parse(ConfigurationManager.AppSettings["SleepSeconds"]) * 1000;
            htmlFileName = ConfigurationManager.AppSettings["HtmlFileName"];
 
            NameValueCollection urls = (NameValueCollection)ConfigurationManager.GetSection("urls");
            for(int i = 0;i < urls.Count;i++)
            {
                testList.Add(new TestUrl(urls.GetKey(i), urls.Get(i)));
            }
 
            // Don't do it more often than every 15 seconds
            if(sleepMilliseconds < 15000)
            {
                sleepMilliseconds = 15000;
            }
        }

The urls are returned as a NameValueCollection that we can iterate over to get the Names and URLs.

Program.cs runs a forever loop in the Main entry point of the application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
            while (true) // run forever
            {
                // Test each URL
                foreach (TestUrl testUrl in testList)
                {
                    double time = Test(testUrl.Name, testUrl.Url);
                    if (time > -1)
                    {
                        testUrl.AddSuccess(time);
                    }
                    else
                    {
                        testUrl.AddFailure();
                    }
                }
 
                OutputHtml();
 
                // Sleep between iterations. Don't remove this! You can spam
                // the web sites your hitting and may end up getting your IP
                // filtered by their firewall.
                System.Threading.Thread.Sleep(sleepMilliseconds);
            }

Each URL is tested on each iteration of the loop and the HTML output file is updated. You MUST sleep between each iteration or you will flood the server with page requests. If the request is successful a value greater than -1 will be returned and a success will be added to the URL otherwise a failure will be added to the URL.

The actual testing is done in the Test method. We use a WebClient to perform the request. Its DownloadString method is passed a URL and if the request is successful will return a string containing the response from the web server. We start the timer before the call to DownloadString and return the time it took after the call. If the web request fails an exception will be thrown and a time of -1 will be returned.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        // Performance test a URL
        static double Test(string name, string url)
        {
            double time = -1.0;
 
            Console.WriteLine("Testing {0}", name);
            using (WebClient wc = new WebClient())
            {
                wc.CachePolicy = cachePolicy;
 
                try
                {
                    // Start the timer
                    timer.Start();
 
                    // Request the web page
                    string response = wc.DownloadString(url);
 
                    // Get the time it took
                    time = timer.Time();
                    Console.WriteLine("{0} seconds {1} bytes", time.ToString("0.000"), response.Length);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: {0}", ex.Message);
                }
            }
 
            return time;
        }

The OutputHtml method uses an XMLTextWriter to output the HTML code for our display web page.

The TestUrl and Hour classes just store the statistical information that is being captured. They also output the data in HTML format.

You can download a zip of the source code from the following link:
WebPerfTest Application Source Code

You can download a zip of the executable and defaut config file from this link:
WebPerfTest Executable

Update the config file with your own URLs to test before running the application.

[del.icio.us] [Digg] [Reddit] [Technorati]

RSS feed | Trackback URI

Comments »

No comments yet.

Name (required)
E-mail (required - never shown publicly)
URI
Subscribe to comments via email
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> in your comment.