Last Updated: October 06, 2018
·
1.494K
· danhanly

Benchmarking PHP: Variable Transport Methodologies

During the development of a particularly large script, we looked toward clawing back some time and efficiency through analysing our methodologies. This script involved the use of variables and methods within a fairly complex loop system; loops, essentially, within loops.

Our initial thought was be to refactor the code to include class variables for anything that remained constant throughout the operation; at present they were being passed as parameters to methods where they were required. This variable transport methodology got quite a varied response internally when it was initially proposed. We thought it prudent to do some benchmarking to assess our efforts.

Variable Transport Classes

We created three separate classes, each corresponding to the three things we wanted to test:

  • Method Passing Variables
  • Reference Variables
  • Class Variables

Method Passing Variables

This is the simplest form of variable transport, where the variable is sent to the method where it is required. This keeps the methods quite unitary, whereby any dependencies are injected into the method that requires them. Each time a method is enacted, the variables are created, developing possible additional overhead for each new function.

Read More on Method based Variable Transport

class PassVariable
{
    public function mainFunc()
    {
        $variableName = "Test";
        for ($i = 0; $i < 100000; ++$i) {
            $this->method($variableName);
        }
    }

    protected function method($variableName)
    {
        return $variableName;
    }
}

Reference Variables

Reference variables are variables that you are allowing methods to modify directly. It differs slightly from Method Passing Variables in that an instance of the variable isn’t re-created within the method that requires it. The variable itself, in essence, still belongs to the function that created it, however the methods are able to make use of it. In memory terms, a method has the ‘permissions’ to access the variable’s memory, as much as the method that created it does. The only difference, syntactically, between Method Passing Variables and Reference Variables is the presence of the ‘&’ within the method parameter; thus directing the method to treat this particular variable as a reference.

Read More on Reference based Variable Transport

class ReferenceVariable
{
    public function mainFunc()
    {
        $variableName = "Test";
        for ($i = 0; $i < 100000; ++$i) {
           $this->method($variableName);
        }
    }

    protected function method(&$variableName)
    {
        return $variableName;
    }
}

Class Variables

Class Variables are a variable transport mechanism whereby any variables that remain constant throughout an operation can be saved to a scope which is of a higher level than within the function itself. This methodology is known more commonly as Class Properties and is a core feature of the Object Oriented Programming principles within PHP; Variables is used in this context to provide consistency to the other methodologies. This means that it is immediately accessible to any functions within the class. This is variable transport without variable transport.

Read More on Class Property based Variable Transport

class ClassVariable
{
    protected $variableName;

    public function mainFunc()
    {
        $this->variableName = "Test";
        for ($i = 0; $i < 100000; ++$i) {
           $this->method();
        }
    }

    protected function method()
    {
        return $this->variableName;
    }
}

Benchmarking

The benchmark was a simple, trivial example. The idea was to call a method within a loop that was locked within 100,000 iterations. This method would simply return the variable in question.

We created a vagrant setup with which to test this, using a simple vagrant-based php webserver. This would ensure a vanilla environment with which to run the tests. Each test was run 10 times within the same script and the results were graphed to visualise the outcome. As mentioned, these variable transport methodologies are trivial and as such, even the highest execution time was under a tenth of a second.

Fig A. Variable Transport Methodologies Benchmark Table

Picture

Fig B. Variable Transport Methodologies Benchmark Graph

Picture

As you can see from the above data, the fastest execution was Class Variables, and we’d expected this output. However, what we didn’t expect is that Reference Variables would be slower than the other two methodologies in all cases. Reference Variables, by definition are simply passing references to the objects, rather than the object themselves. By that logic, there’s a lot less data being transported between the methods.

Conclusion

Now, it’s important to consider that this analysis is based upon speed of execution alone, and not upon memory usage, or any number of other potential avenues for assessment. On speed alone, Class Variables are by far the fastest method. Obviously, it's important to note that these methodologies won't always be applicable to every project, and some may require certain ways over others; this is an experiment without context and wouldn't necessarily be indicative of the results when running within a full PHP application.

3 Responses
Add your response

Definitely surprised that Referenced is always slower than Passed, not to mention the fluctuation in the size of the gap between their performance across your tests. I'd have thought Passed would be slower, or they'd be nearly identical - if anyone knows why this isn't the case, I'd love to know!

over 1 year ago ·

I was surprised at that outcome too. I can show the results but alas, cannot explain them. If anyone else know why, I'll be happy with that, too!

over 1 year ago ·

While the outcome is interesting beware of chart junk: there is less than 15% difference between the methods: your x axis is not at zero so the chart seems to exaggerate the difference. I would guess that since the method would have to "look" for a variable passed by reference that would take more cpu cycles (at the advantage of less memory usage) instead of a variable that is local to the method. If you wanted to print or modify something larger (a 500kb return from a web service for example) the results might change because you may have memory issues affecting the results. I prefer class variables so this experiment validates my methods :). Thanks for doing this test!

over 1 year ago ·