Requirements Testing

February 10th, 2006

You are currently browsing the articles from TechToolBlog written on February 10th, 2006.

Performance Testing with PHP

After writing some functions or classes its good idea to make sure your code is executing in a timely fashion, especially for web applications. For PHP I use a function derived from the chronmeter class to look for bottle necks (the function is below or download it here).

We recently ran into a problem of a web form running particular slow. It had the following functionality.

  • Insert some data into 2 mysql tables
  • Grab some data from a Microsoft SQL Database
  • Read in a text file, replace some verbiage, then send out a couple of emails.
  • I architected the form and was letting one of our interns implement it. Everything seemed pretty straight forward - this code should fly. After the site went live, I checked out the form and found it running slow. Using the chronometer function I paired it down to our phpmailer. Turns out we were using php’s built in mail function and not phpmailer.

    After switching to phpmailer and setting the option to smtp, I cut the runtime in half. I then realized we were sending out 2 emails and each time opening/closing an smtp connection. I refactored so only 1 connection was opened. Here are the results of the average form runtime:

  • PHP’s built in mail function: Avg: 3 seconds.
  • PHPMAILER function with 2 connections: 1.5 seconds.
  • PHPMAILER function with 1 connection: .105 seconds
  • To use the chronometer function, simply call it before a class or function call and then call it right after it .


    $chronometer(); //start
    $this->SendSalesEmail($_POST);
    $runtime = chronometer();
    print “SendSalesEmail took: $runtime”;

    $CHRONO_STARTTIME = 0;

    define(”RET_TIME”, “s”); //Can be set to “ms” for milliseconds or “s” for seconds
    function chronometer()
    {
    global $CHRONO_STARTTIME;

    $now = microtime(TRUE); // float, in _seconds_

    if (RET_TIME === ’s’) {
    $now = $now + time();
    $malt = 1;
    $round = 7;
    } elseif (RET_TIME === ‘ms’) {
    $malt = 1000;
    $round = 3;
    } else {
    die(”Unsupported RET_TIME value”);
    }

    if ($CHRONO_STARTTIME > 0) {
    /* Stop the chronometer : return the amount of time since it was started,
    in ms with a precision of 3 decimal places, and reset the start time.
    We could factor the multiplication by 1000 (which converts seconds
    into milliseconds) to save memory, but considering that floats can
    reach e+308 but only carry 14 decimals, this is certainly more precise */

    $retElapsed = round($now * $malt - $CHRONO_STARTTIME * $malt, $round);

    $CHRONO_STARTTIME = $now;

    return $retElapsed;
    } else {
    // Start the chronometer : save the starting time

    $CHRONO_STARTTIME = $now;

    return 0;
    }
    }

    ?>php_chronometer.txt

    Written by Tim on February 10th, 2006 with 2 comments.
    Read more articles on php.