PHP DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Subscribe to PHP Subscribe to Newsletters

Improving Performance by Profiling PHP Applications
Pages: 1, 2

A Benchmark Anecdote

The example was good, but it is really not a good example of how to make decisions related to your site, and especially to your site code. I will use a personal experience that I had while working as a contractor for a company that had a huge Web community on a niche Web site and was having performance problems.



I really didn't understand much of the code because it was written along the years with specific needs -- one block of include files relating to the site translation code, another one to log the site's usage, and so on. We both knew (me and the main programmer of that site) that something needed to be optimized, but didn't know what the problem was.

To shorten the story, I ended up going into the main script and adding several lines of $bench->setMarker() all over the script and its included files. We then analyzed the output of $bench->getProfiling() and were surprised by the outcome. It seemed that the problem was actually related to a function call that was being used hundreds of times on every page to get the translation code for a specific language name (i.e. "en" for "english"). Every time the function was called, the script would do a query to a MySQL database to get the real name from a table.

Related Reading

Programming PHP
By Rasmus Lerdorf, Kevin Tatroe

We ended up creating a cache system for this type of information. In two days we had a huge performance boost, and consequently the number of page views increased by 40% in the first week. All in all, this serves as an interesting example of how profiling your code can help on the general health of your Web application or Web site.

Benchmarking Function Calls

While the Benchmark_Timer() class is very useful in profiling the code on a script or page (and its included files), it is not very scientific, since you have to reload the script several times to get the mean of the profiled values, and it is not very specific to a class or function call.

The other class in the PEAR::Benchmark library, called Benchmark_Iterator, is intended to tackle this very issue -- running a series of executions for a very specific function or class method and displaying its profiling information. Its purpose is to get a consistent response from the benchmarks, since everybody knows that running a script one time and receiving an execution time of 10 seconds doesn't mean that it always performs like that.

In any case, let's see some examples:

<?php
// code to connect to the database here
include_once("DB.php");
$dsn = array(
    'phptype'  => 'mysql',
    'hostspec' => 'localhost',
    'database' => 'database_name',
    'username' => 'user_name',
    'password' => 'password'
);
$dbh = DB::connect($dsn);

function getCreatedDate($id)
{
    global $dbh;

    $stmt = "SELECT created_date FROM users WHERE id=$id";
    // as always, let's use PEAR::DB here
    $created_date = $dbh->getOne($stmt);
    if ((PEAR::isError($created_date)) || 
	    (empty($created_date))) {
        return false;
    } else {
        return $created_date;
    }
}

include_once 'Benchmark/Iterate.php';
$bench = new Benchmark_Iterate;

// run the getDate function 10 times
$bench->run(10, 'getCreatedDate', 1);

// print the profiling information
print_r($bench->get());
?>

The code above will generate output similar to this:

Array
(
    [1] => 0.055413007736206
    [2] => 0.0012860298156738
    [3] => 0.0010279417037964
    [4] => 0.00093603134155273
    [5] => 0.00094103813171387
    [6] => 0.00092899799346924
    [7] => 0.0010659694671631
    [8] => 0.00096404552459717
    [9] => 0.0010690689086914
    [10] => 0.00093603134155273
    [mean] => 0.0064568161964417
    [iterations] => 10
)

This should be pretty self explanatory -- the mean item shows the average value for all 10 iterations of the getCreatedDate() function. The benchmark should probably run for more than a thousand iterations, but this example is good enough :).

I hope that with this article I've given some insight into practical ideas of how to quickly profile PHP scripts. Please be aware that analyzing your code is not something simple, as you need to know a lot about the language's specific features. However, adding timers while testing your code will help you isolate the sluggish functions and using iterations will help test them until you figure out the correct optimizations.

Joao Prado Maia is a web developer living in Houston with more than four years of experience developing web-based applications and loves learning new technologies and programming languages.


Return to the PHP DevCenter.




Tagged Articles

Be the first to post this article to del.icio.us

Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com