The Benchmark_Profiler Class
The Benchmark_Profiler class provides a set of methods that return formatted profiling information. The prototypes of the most used methods of this class are:
- void enterSection(string $name): This function enters a code section. The $name parameter represents the name of the code section.
- void leaveSection(string $name): This function leaves a code section. The $name parameter represents the name of the code section.
- void display([string $format = 'auto']): This function returns formatted profiling information. The $format parameter represents the desired output format: auto (the default), plain or html.
Here's the code to apply the Benchmark_Profiler class to the iterative and recursive Fibonacci solutions:
// Iterative version
<?php
require_once 'Benchmark/Profiler.php';
//create an instance of the Benchmark_Iterate class
$profiler = new Benchmark_Profiler(TRUE);
function fibonacci(){
global $profiler;
$a=0;$b=1;
for ($i = 0; $i < 10; $i++) {
//Enters code section
$profiler->enterSection('fibonacci'.$i);
$s=$a+$b;
$a=$b;
$b=$s;
//Leaves code section
$profiler->leaveSection('fibonacci'.$i);
}
//Returns formatted profiling information
$profiler->display();
return;
}
fibonacci();
?>
// Recursive version
<?php
require_once 'Benchmark/Profiler.php';
//create an instance of the Benchmark_Iterate class
$profiler = new Benchmark_Profiler(TRUE);
//this function implements the recursive solution
//for the fibonacci problem
function fibonacci($n){
if(($n>=0)and($n<2))
{
return 1;
}
else
{
return fibonacci($n-1)+fibonacci($n-2);
}
}
global $profiler;
for ($i = 0; $i < 10; $i++) {
//Enters code section
$profiler->enterSection('fibonacci'.$i);
fibonacci($i).'<br />';
//Leaves code section
$profiler->leaveSection('fibonacci'.$i);
}
//Returns formatted profiling information
$profiler->display();
return;
?>
Result Comparison
The iterative result is:
| |
Total Ex. Time |
Calls |
Percentage |
Callers |
| fibonacci0 |
0.00025200843811035 |
1 |
N/A |
Global (1) |
| fibonacci1 |
4.6968460083008E-005 |
1 |
N/A |
Global (1) |
| fibonacci2 |
3.814697265625E-005 |
1 |
N/A |
Global (1) |
| fibonacci3 |
5.1021575927734E-005 |
1 |
N/A |
Global (1) |
| fibonacci4 |
5.2928924560547E-005 |
1 |
N/A |
Global (1) |
| fibonacci5 |
5.6028366088867E-005 |
1 |
N/A |
Global (1) |
| fibonacci6 |
3.7908554077148E-005 |
1 |
N/A |
Global (1) |
| fibonacci7 |
4.0054321289063E-005 |
1 |
N/A |
Global (1) |
| fibonacci8 |
3.6954879760742E-005 |
1 |
N/A |
Global (1) |
| fibonacci9 |
0.00029301643371582 |
1 |
N/A |
Global (1) |
The recursive result is:
| |
Total Ex. Time |
Calls |
% |
Callers |
| fibonacci0 |
0.0001368522644043 |
1 |
N/A |
Global (1) |
| fibonacci1 |
0.00031614303588867 |
1 |
N/A |
Global (1) |
| fibonacci2 |
8.4877014160156E-005 |
1 |
N/A |
Global (1) |
| fibonacci3 |
7.9870223999023E-005 |
1 |
N/A |
Global (1) |
| fibonacci4 |
0.00011897087097168 |
1 |
N/A |
Global (1) |
| fibonacci5 |
0.0001227855682373 |
1 |
N/A |
Global (1) |
| fibonacci6 |
0.00016498565673828 |
1 |
N/A |
Global (1) |
| fibonacci7 |
0.00038599967956543 |
1 |
N/A |
Global (1) |
| fibonacci8 |
0.00036907196044922 |
1 |
N/A |
Global (1) |
| fibonacci9 |
0.00057005882263184 |
1 |
N/A |
Global (1) |
Getting Benchmark Results Graphically
Getting raw numbers is useful, but often it's more useful to view benchmarking information in a more palatable form, such as bar or pie charts. You can add graphical capabilities to the
Timer tests by extending the
fibonacci_iterative_timer.php application, using SVG to obtain a bar/pie chart image that visually shows the time required to run each iteration of the main loop. To do that, you plot the last column from the Timer Results table—giving a visual representation of the "ex time" column:
<?php
require_once 'Benchmark/Timer.php';
function fibonacci(){
//create an instance of the Benchmark_Timer class
$timer = new Benchmark_Timer();
//Set "Start" marker
$timer->start();
$a=0;$b=1;
for ($i = 0; $i < 15; $i++) {
$s=$a+$b;
//Set the markers
$timer->setMarker('f'.$i);
$a=$b;
$b=$s;
}
//Set "Stop" marker
$timer->stop();
//Returns formatted informations
echo '<table>';
echo '<tr>';
echo '<td>';
$timer->display();
echo '</td>';
echo '<td>';
//Get the profiler info as an associative array
$profiling = $timer->getProfiling();
//serialize the $profiling
$ser = serialize($profiling);
// Display all the information: name, time,
// difference between two consecutive
// markers, and total time
echo "<embed src='DiagramSvg.php?profile=".$ser."' width='900'
height='500' type='image/svg+xml'
pluginspage='http://www.adobe.com/svg/viewer/install/' />";
echo '</td>';
echo '</tr>';
echo '</table>';
}
//start the process
fibonacci();
?>
 | |
| Figure 1. Graphical Representation of Benchmark Results: This view shows the raw data and superimposed pie and bar charts for 15 iterations of the Fibonacci method. |
The preceding code outputs an HTML page containing a table with the raw profiling information you've already seen. It uses that to generate two SVG-formatted charts (see
Listing 4), which it displays using the Adobe SVG player in the right column of the table.
Figure 1 shows the table the code returns, letting users view possible results for 15 Fibonacci iterations.
As you can see, adding benchmarking in PHP using this PEAR is a simple and linear task. It's not limited to new code, either; implementing benchmarking for your existing PHP code doesn't require much time, and the results are easy to understand and process—leaving few excuses for not optimizing your PHP applications! What you might consider an unnecessary step now, can really make a big difference later.