Comparing Files and Databases with PHP Benchmarking Applications

If you’re a web developer who wants to learn how to create simple benchmarking scripts with PHP, this set of comprehensive articles will offer you a friendly introduction to the subject. Welcome to the final part of the series “Benchmarking Applications with PHP.” Made up of three tutorials, this series teaches you, via copious hands-on examples, how to implement some simple approaches to determine the performance of different PHP applications.

As you probably realized from the second tutorial of the series, creating timing scripts either by using a procedural methodology or an object-based approach is a hassle-free process. It can be easily achieved by anyone with an intermediate background in PHP.

More specifically, all the practical examples that you saw in the previous parts used the neat “microtime()” built-in PHP function as the real workhorse. It’s handy for constructing timer functions or eventual classes. In either case, you can expand the functionality of all these examples and build a full-featured timing system that, obviously, can be implemented for benchmarking purposes too.

This large, complex subject offers numerous possibilities for experimentation, which means that you’ll surely have tons of fun creating timing systems with PHP.

Now it’s time to pay attention to the topics that will be discussed in this final part of the series. In the preceding tutorial I showed you a few understandable examples of how to use a timer class to spot the differences between fetching rows from a MySQL database table using HTTP compression and without it. This article, then, will be focused on evaluating different scripts that fetch sets of records, first from a database, and then from flat files.

The experience sounds really interesting. Thus, let’s not waste more time in preliminaries and start reading!

{mospagebreak title=Reading data from a sample database table}

To continue testing the benchmarking capabilities offered by PHP, I will first perform a simple comparison between fetching rows from the sample “USERS” database table that you saw in the previous article and retrieving the same data, but this time coming from a flat text file.

In doing so, it’ll be possible to determine which approach is faster, depending on the benchmarking conditions (remember that all the examples will be tested on a local server). Given that, first let me show you the script that fetches rows from the mentioned database table in conjunction with the corresponding classes used by the code snippet listed below. Take a look, please:


// define ‘Timer’ class

class Timer{

private $elapsedTime;

// start timer

public function start(){

if(!$this->elapsedTime=$this->getMicrotime()){

throw new Exception(‘Error obtaining start time!’);

}

}

// stop timer

public function stop(){

if(!$this->elapsedTime=round($this->getMicrotime()-$this->elapsedTime,5)){

throw new Exception(‘Error obtaining stop time!’);

}

return $this->elapsedTime;

}

//define private ‘getMicrotime()’ method

private function getMicrotime(){

return microtime(true);

}

}

// define ‘MySQL’ class

class MySQL{

private $conId;

private $host;

private $user;

private $password;

private $database;

private $result;

const OPTIONS=4;

public function __construct($options=array()){

if(count($options)!=self::OPTIONS){

throw new Exception(‘Invalid number of connection parameters’);

}

foreach($options as $parameter=>$value){

if(!$value){

throw new Exception(‘Invalid parameter ‘.$parameter);

}

$this->{$parameter}=$value;

}

$this->connectDB();

}

// connect to MySQL

private function connectDB(){

if(!$this->conId=mysql_connect($this->host,$this->user,$this->password)){

throw new Exception(‘Error connecting to the server’);

}

if(!mysql_select_db($this->database,$this->conId)){

throw new Exception(‘Error selecting database’);

}

}

// run query

public function query($query){

if(!$this->result=mysql_query($query,$this->conId)){

throw new Exception(‘Error performing query ‘.$query);

}

return new Result($this,$this->result);

}

}


// define ‘Result’ class

class Result {

private $mysql;

private $result;

public function __construct($mysql,$result){

$this->mysql=$mysql;

$this->result=$result;

}

// fetch row

public function fetchRow(){

return mysql_fetch_assoc($this->result);

}

// count rows

public function countRows(){

if(!$rows=mysql_num_rows($this->result)){

throw new Exception(‘Error counting rows’);

}

return $rows;

}

// count affected rows

public function countAffectedRows(){

if(!$rows=mysql_affected_rows($this->mysql->conId)){

throw new Exception(‘Error counting affected rows’);

}

return $rows;

}

// get ID form last-inserted row

public function getInsertID(){

if(!$id=mysql_insert_id($this->mysql->conId)){

throw new Exception(‘Error getting ID’);

}

return $id;

}

// seek row

public function seekRow($row=0){

if(!is_int($row)||$row<0){

throw new Exception(‘Invalid result set offset’);

}

if(!mysql_data_seek($this->result,$row)){

throw new Exception(‘Error seeking data’);

}

}

}


try{

// instantiate ‘Timer’ class

$timer=new Timer();

// start timer

$timer->start();

// connect to MySQL

$db=new MySQL(array
(‘host’=>’host’,’user’=>’user’,’password’=>’password’,’database’=>’database’));

$result=$db->query(‘SELECT * FROM users’);

while($row=$result->fetchRow()){

echo ‘ID: ‘.$row['id'].’ Name: ‘.$row['name'].’ Email: ‘.$row['email'].'<br />';

}

// stop timer

$elapsedTime=$timer->stop();

// display elapsed time

echo ‘Time spent in fetching database rows was ‘.$elapsedTime.’ seconds';

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


/* displays the following:


ID: 1 Name: user1 Email: user1@domain.com

ID: 2 Name: user2 Email: user2@domain.com

ID: 3 Name: user3 Email: user3@domain.com

ID: 4 Name: user4 Email: user4@domain.com

ID: 5 Name: user5 Email: user5@domain.com

ID: 6 Name: user6 Email: user6@domain.com

ID: 7 Name: user7 Email: user7@domain.com

ID: 8 Name: user8 Email: user8@domain.com

ID: 9 Name: user9 Email: user9@domain.com

ID: 10 Name: user10 Email: user10@domain.com

Time spent in fetching database rows was 0.00544 seconds


In this case, you can see that the process for retrieving the ten rows stored in the above “USERS” database table took approximately 0.0054 seconds. The program demonstrates how easy it is to benchmark a particular script by using the “Timer” class listed above.

Well, now that you know how long it took to retrieve the previous rows from the respective database table, let’s find out if the above performance test can be improved by retrieving the same records from a flat file. Sounds pretty interesting, doesn’t it?

Therefore, if you want to learn how this benchmarking test will be performed, jump into the following section and keep reading.

{mospagebreak title=Reading data from a flat text file}

As I said in the section that you just read, the next benchmarking example that I plan to create here relies on fetching the ten rows that you saw before using a plain text file. First off, I need to define a class that fetches the records from the text file. Therefore, below I listed the signature for this class. Here it is:


// define ‘FileProcessor’ class

class FileProcessor{

private $data=array();

private $dataFile;

public function __construct($dataFile){

if(!file_exists($dataFile)){

throw new Exception(‘Invalid data file!’);

}

$this->dataFile=$dataFile;

}

// read data from file

public function readFile(){

if(!$contents=file_get_contents($this->dataFile)){

throw new Exception(‘Error reading data file!’);

}

return nl2br($contents);

}

// write data to file

public function writeFile(){

if(!$fp=fopen($this->dataFile,’a+’)){

throw new Exception(‘Error opening data file!’);

}

foreach($this->data as $line){

if(!fwrite($fp,$line."n")){

throw new Exception(‘Error writing data file!’);

}

}

fclose($fp);

}

// add data to $data array

public function addData($data){

if(!is_string($data)){

throw new Exception(‘Data must be a string!’);

}

$this->data[]=$data;

}

}

Indeed, the signature of the above “FileProcessor” class is really easy to follow. In short, all that this class does is read and write data using a flat text file for storing purposes. Of course, most of its methods can be significantly improved, but for now, it’s more than enough for setting up this benchmarking example.

Okay, having showed you how the previous file processor class looks, let me show you a couple of short scripts. The first one inserts ten new records into a sample text file, and the second one reads this data and prints the contents on the browser.

That being said, here is the listing for the corresponding examples:


// example using ‘FileProcessor’ class (writes data to file)

try{

// instantiate ‘Timer’ class

$timer=new Timer();

// instantiate ‘FileProcessor’ object

$fileProc=new FileProcessor(‘data_file.txt’);

// start timer

$timer->start();

$fileProc->addData(‘ID: 1 Name: user1 Email: user1@domain.com’);

$fileProc->addData(‘ID: 2 Name: user2 Email: user2@domain.com’);

$fileProc->addData(‘ID: 3 Name: user3 Email: user3@domain.com’);

$fileProc->addData(‘ID: 4 Name: user4 Email: user4@domain.com’);

$fileProc->addData(‘ID: 5 Name: user5 Email: user5@domain.com’);

$fileProc->addData(‘ID: 6 Name: user6 Email: user6@domain.com’);

$fileProc->addData(‘ID: 7 Name: user7 Email: user7@domain.com’);

$fileProc->addData(‘ID: 8 Name: user8 Email: user8@domain.com’);

$fileProc->addData(‘ID: 9 Name: user9 Email: user9@domain.com’);

$fileProc->addData(‘ID: 10 Name: user10 Email: user10@domain.com’);

// write data to file

$fileProc->writeFile();

// stop timer

$elapsedTime=$timer->stop();

echo ‘Writing data to file took ‘.$elapsedTime.’ seconds';

 

/*

displays the following

Writing data to file took 0.00124 seconds

*/

 

}

catch(Exception $e){

echo $e->getMessage();

exit();

}

 

// example using ‘FileProcessor’ class (reads data from file)

try{

// instantiate ‘Timer’ object

$timer=new Timer();

// instantiate ‘FileProcessor’ object

$fileProc=new FileProcessor(‘data_file.txt’);

// start timer

$timer->start();

// read data from file

$data=$fileProc->readFile();

// stop timer

$elapsedTime=$timer->stop();

echo ‘File data is listed below: <br />’.$data;

echo ‘Reading data from file took ‘.$elapsedTime.’ seconds';

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


/* displays the following:


File data is listed below:

ID: 1 Name: user1 Email: user1@domain.com

ID: 2 Name: user2 Email: user2@domain.com

ID: 3 Name: user3 Email: user3@domain.com

ID: 4 Name: user4 Email: user4@domain.com

ID: 5 Name: user5 Email: user5@domain.com

ID: 6 Name: user6 Email: user6@domain.com

ID: 7 Name: user7 Email: user7@domain.com

ID: 8 Name: user8 Email: user8@domain.com

ID: 9 Name: user9 Email: user9@domain.com

ID: 10 Name: user10 Email: user10@domain.com

Reading data from file took 0.00061 seconds

*/


As you can see, the first example populates the sample “data_file.text” file with exactly ten records and finalizes its execution by displaying the amount of time this process took. However, I’d like you to pay attention to the second case, where things are definitely more interesting. In this particular example, the reverse process is performed — the data is retrieved from the mentioned text file and echoed on screen.

If you compare the benchmarking values displayed when fetching the rows from the previous database table and when retrieving the data from the respective text file, then you’ll realize that this last case is significantly faster.

Even though all the examples were tested on a local server, the “Timer” class that was used in all cases was very useful for evaluating the performances of different PHP scripts. Didn’t I tell you that benchmarking scripts with PHP was easy?

Okay, at this point, you hopefully understand how to create simple timing scripts with PHP. However, we’ve not come to the end of this journey yet. In the final section of this article, I’ll show you a concluding example that will evaluate the performance of another sample class that will read and write data by way of a text file too.

To see how this final example will be developed, click on the link and keep reading.

{mospagebreak title=Reading and writing compressed file data}

To finish this trip, where the performance of different scripts is roughly evaluated via a “Timer” class, the final example that I plan to create here will be based on defining a brand new file processor class. This class will be capable of reading and writing compressed data by utilizing a text file.

Basically, the definition of this file processing class looks like this:


class FileProcessor{

private $data=array();

private $dataFile;

public function __construct($dataFile){

if(!file_exists($dataFile)){

throw new Exception(‘Invalid data file!’);

}

$this->dataFile=$dataFile;

}

// read data from file

public function readFile(){

if(!$contents=file_get_contents($this->dataFile)){

throw new Exception(‘Error reading data file!’);

}

return $contents;

}

// write compressed data to file

public function writeFile(){

$data=”;

if(!$fp=fopen($this->dataFile,’a+’)){

throw new Exception(‘Error opening data file!’);

}

foreach($this->data as $line){

$data.=$line."n";

}

fwrite($fp,gzencode($data,9));

fclose($fp);

}

// add data to $data array

public function addData($data){

if(!is_string($data)){

throw new Exception(‘Data must be a string!’);

}

$this->data[]=$data;

}

}


As shown above, the “FileProcessor” class looks nearly identical to the one used with previous examples. However, its main difference rests on the fact that it compresses the corresponding input data before saving it to a file. This should eventually decrease the time required for reading the content.

Well, in this case, I used the term “eventually” because reality tells a different story. There’s no significant improvement if you compare this example with the previous one, which works with uncompressed data.

To demonstrate this concept, take a look at the following benchmarking script:


// example using ‘FileProcessor’ class (reads compressed data from file)

try{

// instantiate ‘Timer’ object

$timer=new Timer();

// instantiate ‘FileProcessor’ object

$fileProc=new FileProcessor(‘data_file.txt’);

// start timer

$timer->start();

// read compressed data from file

$fileProc->readFile();

// stop timer

$elapsedTime=$timer->stop();

echo ‘reading compressed data to file took ‘. $elapsedTime.’ seconds';

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


/*

displays the following:

Reading compressed data from file took 0.00063 seconds

*/


In this specific case, reading compressed data from the corresponding data file doesn’t introduce a significant performance improvement (we are taking into account that this script has been tested only locally).

Nevertheless, if a similar file processing application is tested remotely in real conditions, working with compressed data should result in better performance, depending strongly on different testing environments. Naturally, there’s plenty of room to experiment here. Thus, I suggest you use a benchmarking script for testing your applications in real world conditions.

Final thoughts

That’s all for now. In this three-part series, you hopefully learned how to create simple benchmarking scripts that use the “microtime()” built-in PHP function as the main foundation for developing timing functions and classes.

Obviously, evaluating the performance of a specific PHP application depends on many factors, and in this case, I only showed you a few illustrative examples of how to use the remarkable timing capabilities provided natively by PHP.

See you in the next PHP tutorial!

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye