Benchmarking PHP
Featuring PEAR's Benchmark module.
I recently needed some quick code timing information so I wrapped some function
calls with $current = time()
and then subtracted the results. Then I tried it
with microtime()
instead. Then I decided to browse PEAR for some kind of benchmarking tool.
Here are some notes on what PEAR’s Benchmark has to offer.
Iterate
Benchmark_Iterate
is the classic “run something n number of times” kind of
benchmark. It returns the time each execution took as well as the mean.
require_once 'Benchmark/Iterate.php';
function doSomething($arg)
{
return $arg += 100;
}
$benchmark = new Benchmark_Iterate;
$benchmark->run(100000, 'doSomething', 100);
$results = $benchmark->get();
$results['iterations']
returns the number of iterations (100000 in this case)$results['mean']
returns the mean iteration time- In this case, there will also be
$results[1]
through to$results[100000]
with each individual iteration time. Note the indexes go from 1 to n, not 0 to n-1
Timer
Benchmark_Timer
allows you to set markers at various points in your code.
It keeps track of the time elapsed between markers as my original time()
and microtime()
example did.
require_once 'Benchmark/Timer.php';
$timer = new Benchmark_Timer();
$timer->setMarker('start work');
for ($i=0; $i < 100000; $i++) {
$a = sprintf("%.2f", $i);
}
$timer->setMarker('end word');
$results = $timer->getProfiling();
$timer->display();
The display()
method will print out a table with your results. Or, you can access the raw results with getProfiling()
.
Profiler
Benchmark_Profiler
is similar to Benchmark_Timer
except it’s meant to
be enclosed in function and methods. You can also nest various things.
require_once 'Benchmark/Profiler.php';
$profiler = new Benchmark_Profiler();
$profiler->start();
doSomething();
doSomethingElse();
$profiler->stop();
$profiler->output();
Not as simple as that though; doSomething() and doSomethingElse() look like this:
function doSomething() {
global $profiler;
$profiler->enterSection('doSomething');
// do lots of work
$profiler->leaveSection('doSomething');
}
function doSomethingElse() {
global $profiler;
$profiler->enterSection('doSomethingElse');
doSomething();
// do even more work
$profiler->leaveSection('doSomethingElse');
}
Note the nested call in doSomethingElse(). Benchmark_Profiler
will handle
this correctly and show the profile results as expected.
As with Benchmark_Timer
, the output()
method will print out a table with your results. You can get at the data for a particular section by passing the section name to getSectionInformations()
or data for all sections with getAllSectionsInformations()
.
That’s it
Remember, profile before optimizing.