Benchmarking PHP code

Code tuning is an essential part of programming. But most programmers would rather try to complete the project in hand then spend time optimizing a piece of code. A well tuned and optimized code block can speedup your application by an order of magnitude or even more.

Many people confuse profiling with benchmarking. A profiler is a analysis tool that lets you measure the performance of code at runtime. Profiling an application lets you find bottlenecks in your application code. You can find which part of your code is taking most of the time, you can than optimize that part of code. For example if there are 4 functions in your application, profiling may report the following distribution:

function a: 68%
function b: 12%
function c: 1.3%
function d: 18.7%

i.e function ‘a’ accounts for about 70% of the execution time in your application; if you can optimize that function it will boost your application performance considerably. If you had executed the above code on a laptop, and than executed the same on a fast server the code may run in half the time, but the distribution will remain the same. The distribution is what is important in profiling.

Benchmarking is different. It lets you find exactly how long it takes to execute a piece of code. For example I have developed two versions of a sorting algorithm for a application : Sort1(), and Sort2(). If I’ve to find which is faster than I can use a benchmarking software for the same.

To take a contrived example, I recently implemented a Linked List class in PHP (brushing up on my data structure skills), with all the usual functions a linked-list requires – ‘deleteNode‘, ‘insertFirstNode‘, ‘insertLastNode‘, ‘reverseList‘ etc. I was quite happy with the outcome untill I ran a benchmark between two functions – ‘insertFirstNode‘ and ‘insertLastNode‘. Here is a benchmark report for the two functions for various amount of nodes, in table and graph format. The last column shows by how much the ‘insertLastNode‘ is slower than the ‘insertFirstNode‘ function.


benchmark2

As you can see from the report ‘insertLastNode‘ takes exponential time to insert nodes. For example, when inserting 3000 nodes, ‘insertLastNode‘ is 30 times slower then ‘insertFirstNode‘. The reason for this is that ‘insertLastNode‘ has to traverse the entire list to find the last node before adding a new node, while ‘insertFirstNode‘ always adds a new node at the beginning of the list. The simple solution as all you ‘data structure fans’ know is to add a pointer that points to the last node of the list; so every time you have to add a node to the end of the list you use the end node pointer. After making the necessary changes I ran the benchmark and here are the results.

benchmark3

As you can see now both the functions take an equal amount of time to insert a node. Before the code tuning ‘insertLastNode’ took more than 6 seconds to insert 3000 nodes, while after tuning less than quarter of a second.

The whole point of this exercise is to tell you that code tuning can make a tremendous difference to how your application performs.

Installation
You can download the Benchmark pacakage from here or use the pear installer like below:

c:\pear install Benchmark

Using the package:
Using the package for benchmarking is simple enough. A implementation is shown below.

<?php
 
    /* The following sample function is what we
       want to test */
 
    function someFunction()
    {
        for($i=1; $i < 1000; $i++)
            $d = sqrt($i);
    }
 
 
    /* include the PEAR::Benchmark package */
    require_once 'Benchmark/Iterate.php';
 
    $bench = new Benchmark_Iterate;
 
    /* Run the above function 100 times.
       If you want to pass parameters to the function,
       you can add it after the function name like this:
       $bench->run(100, 'someFunction', para1, para2, para n);
    */
    $bench->run(100, 'someFunction');
 
    /* Get the results */
    $result = $bench->get();
 
    /* Display the mean time the function 'someFunction'
       takes to execute */
    print $result['mean'];
 
?>

Output:

0.022045

One thought on “Benchmarking PHP code

Comments are closed.