Improving Performance by Profiling PHP Applications

One of the best things about programming in PHP is how easy it is to learn the language and its libraries. Everything seems to fit together and you can almost guess how to do a specific task, even not knowing much about the function that you need to use. A lot of times you will just try doing something and be surprised that the language has that specific feature.

All of this is very nice, but it takes a little while to get to know PHP's tricks, especially those related to performance and memory consumption. There are lots of subtle things in PHP that can save a lot of memory and give a small extra boost in performance. This article serves as an introduction to profiling PHP applications, and to making changes to a script and comparing the values of the optimizations.

To quote the dictionary, a profile is a formal summary or analysis of data, often in the form of a graph or table, representing distinctive features or characteristics. By placing timers within the code and running them over and over, we can obtain a profile of how fast or slow specific areas of a program are executed. This data can be used to discover bottlenecks and other areas that can be optimized to improve the program's performance.

Assuming you have read my series of articles about PEAR, the concept of profiling PHP scripts is covered in a simple manner by a PEAR library. We will use this library to create examples of profiling scenarios, as this is the easiest and most compatible way to analyze your current code. You don't even have to use a commercial product or compile an extension to profile your code.

The library name is PEAR::Benchmark and it is very useful to profile and do quick benchmarks on your code set. One of the classes available in this library is named Benchmark_Timer() and tracks the time difference from one function call to the next. When you are done with the benchmark, you can get verbose result of the script execution. It is as simple as this:

<?php
include_once("Benchmark/Timer.php");
$bench = new Benchmark_Timer;
$bench->start();
$bench->setMarker('Start of the script');
// now sleep for a few seconds
sleep(5);
$bench->stop();
// get the profiling information from this timer
print_r($bench->getProfiling());
?>

That might seem like a bunch of weird numbers, but it is very useful if used in a bigger scale.

Dissecting the Numbers

As most people will guess, the topmost array entries are the actual calls to the Benchmark_Timer() class, like $bench->start(), $bench->setMarker(), and $bench->stop(). The number associated with each of these array entries is pretty straightforward. Let's look closer at them:

The entry time refers to the UNIX timestamp of when the call to the start() method of Benchmark_Timer() was done. The diff item shows the difference in time between this call and the previous one -- since there is no previous one, it shows a dash. The total item is the total time of execution since the beginning of the benchmark until this specific method call. Seeing the output of the next array entry is useful as well.

We can see from these numbers that the call to $bench->setMarker(....) was made 9.8943710327148E-05 seconds after the call to $bench->start(). No need to go after a calculator, that means 0.0000989 seconds. :)