Friday, March 21, 2008

PHP load testing script to run with cron

We've been interested in seeing what the response time is for some pages of ours on a server. So to test this I came up with the following script which uses curl to open the url, save the contents of the page called to file, close it and while it does this, time the start and end then report on the findings in a database. Here's some sample code:

$hostname_cg = "localhost";
$database_cg = "dbname";
$username_cg = "dbuser";
$password_cg = "dbpass";
$cg = mysql_connect($hostname_cg, $username_cg, $password_cg) or trigger_error(mysql_error(),E_USER_ERROR);

if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "")
$theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;

$theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

switch ($theType) {
case "text":
$theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
case "long":
case "int":
$theValue = ($theValue != "") ? intval($theValue) : "NULL";
case "double":
$theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
case "date":
$theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
case "defined":
$theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
return $theValue;

function microtime_float()
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
function InsertDB($startTime, $endTime, $totalTime, $Page){
global $database_cg, $cg;
$insertSQL = sprintf("INSERT INTO tblpagetest (StartTime, EndTime, TotalTime, Page) VALUES (%s, %s, %s, %s)",
GetSQLValueString($startTime, "text"),
GetSQLValueString($endTime, "text"),
GetSQLValueString($totalTime, "text"),
GetSQLValueString($Page, "text"));

mysql_select_db($database_cg, $cg);
$Result1 = mysql_query($insertSQL, $cg) or die(mysql_error());

// $page - address of page to download and test.
// $savefile - file to save to on local disk
// $pagename - descriptive name for database entry
// $numberoffiles - this will recursively download the amount of files defined and download them to disk.

function getPage($page, $savefile, $pagename, $numberoffiles){

$time_start = microtime_float();

$ch = curl_init($page);
$fp = fopen($savefile, "w");

curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);


if($numberoffiles <> 0){ // If we have defined a number of files, create a sequential sequence of images which will fulfill the requested amount and download them one at a time.
for ($counter = 1; $counter <= $numberoffiles; $counter++)
$image = "".$counter.".gif";
$chimage = curl_init($image);
$fpimage = fopen("image".$counter.".gif", "w");

curl_setopt($chimage, CURLOPT_FILE, $fpimage);
curl_setopt($chimage, CURLOPT_HEADER, 0);

//echo $image."copied";

$time_end = microtime_float();
$total_time = $time_end - $time_start;

InsertDB($time_start, $time_end, $total_time, $pagename);

print $pagename." returned in $total_time seconds


function getmypages(){

getPage("", "website.txt", "website test", 78);



Sample Database table schema:

CREATE TABLE `tblpagetest` (
`ID` int(11) NOT NULL auto_increment,
`StartTime` varchar(255) NOT NULL,
`EndTime` varchar(255) NOT NULL,
`TotalTime` varchar(255) NOT NULL,
`Page` varchar(255) NOT NULL,
`DateCreated` timestamp NOT NULL default CURRENT_TIMESTAMP,

NOTE: Although this script takes into consideration the size of the page with all assets (use this site to find out how many files link off from the page, and the overall page size it does not take into consideration multi-concurrent connections as a normal browser would. E.g. if your index page contains 90 items and totals 400k, you should call 90 images that are 4.4k in size to simulate the load on the server.

I'm pretty sure that there are other scripts out there that make this more efficient and if you know of them, please let me know where I can download and test from. Thanks.

PHP error reporting

I've been asked a number of times in the past on how to best handle errors in php. There are two that I currently use. One would be to manually check the values of a variable to see if it conforms to various criteria and then echo to the page on the errors that were encountered. Another would be to trigger an error event which could be saved to the error log files, inserted into a database, saved to a custom error log or echoed out to the page. Here's some code which gives examples of both:

$errors = true;
if($myimage == 'var'){ $errors = false; } else{ echo "there was an error!";}

// Override PHP.ini's setting of error reporting and intercept all errors with our own error handler

if (!function_exists("myErrorHandler")) {
function myErrorHandler($errno, $errstr, $errfile, $errline){
global $printErrors, $DBLogErrors, $emailErrors;
switch ($errno) {
case E_USER_ERROR : // 256
$errorMessage = "My ERROR [$errno] $errstr
$errorMessage .= " Fatal error on line $errline in file $errfile";
$errorMessage .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")
$errorMessage .= "Aborting...
echo $errorMessage;
default :

$errorMessage = "UNSPECIFIED ERROR [$errno] $errstr
$errorMessage .= " error on line $errline in file $errfile";
$errorMessage .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")
$errorMessage .= "Aborting...

echo $errorMessage;
/* Don't execute PHP internal error handler */
return true;