We've all been there before, you submit a pull request and moments later you get a comment like: "Hey you should use a native function here, they are so much faster" or "You can declare this final, that way we save some processing power".
It's great that we as developers keep an eye on this, but how true are these thing. And are they still a thing in newer PHP versions?
To the laboratory
Time to put some of these "good practices" to the test. I've selected 10-speed tricks that I've picked up over the years and we're going to check how relevant they still are in PHP7.2.
So how are we going to test this? I've set up a small project that we are going to be running natively (no Docker, no vagrant) in MacOs (version: 10.13.5). The PHP version is the latest version currently on brew (PHP 7.2.8).
The benchmark itself uses PHPBench and we are going to compare each "trick" to its standard alternative. They are separate methods that each will be running 1000 times over 5 iterations. So that means we will run each test 5000 times grouped over 5 results. That way we can minimise deviations and extract meaningful results.
Sounds like fun? Let's bust some myths.
But before we begin, please a word of warning. We are going to zoom in on these claims. Some of these results might seem pretty high but that is only because we only run very small pieces of code. The results might not be that extreme in your day to day code.
Are single quotes faster than double quotes?
Let's start out with a classic. As single quotes are encouraged by PSR we all might be getting some small speed bonuses without knowing it. We will test with this code:
And these are the results:
Turns out that single quotes are about 5% slower in this test.
is JSON faster than XML?
Sometimes we like to use JSON or XML to setup validation or config files. Most people like to use JSON over XML due to readability reasons. But is it also faster?
A quick word of warning here, we will be using the native xmlrpc_encode en xmlrpc_decode functions. These are very experimental and not fully implemented. We could be using packages for this, something I would certainly advise in real projects, but that would skew the results too much (as we need to load them in etc). So here is the code:
And unsurprisingly here are the results:
The native experimental functions that deal with XML are way slower in our tests.
Using loads of layered objects is way slower?
This one will be a bit messy to display. We are going to new up some classes and send the parameters down 3 layers. There we execute the same function as we otherwise would.
I think we all know that the new-ing up of classes will lose us some time, but let's see how much time we lose.
Unsurprisingly the new-ing up of classes takes some time. In this case, it comes down to about 25% slower. This obviously doesn't mean you shouldn't be using classes anymore. Personally, I will always prefer maintainability over speed.
Native array functions should be faster than loops, right?
This is a classic. It's said that native array functions are faster than for each loop because they are native C functions. This is the code we will be running:
I'm going to be totally honest here and say that I've run this test a few times now, cause I couldn't really believe the results:
Turns out that in this test the array_map method is slower than the foreach. This probably has something to do with the anonymous function.
$row[’id’] is 7 times faster than $row[id] ?
I've never heard of this one. Apparently, it's a thing:
Turns out it doesn't really make a lot of difference, at least not in the 700% range.
The string fetching is even marginally slower in our test by 2%.
Are throws super expensive?
Error handling is an important part of any application, but it is said you should be a bit wary of using extensive amounts of try-catch blocks. Time to put it to the test.
And the results:
Unsurprisingly we lose some time on the errorHandling. But personally, I would always recommend having more error handling over having less.
What is the impact of unused vars?
Most static analysis tools tend to either complain about unused vars or straight up to remove them for you.
As unused vars in your code serve no real benefit, it doesn't really make sense to keep them. That said, let's take a look at the cost.
and the results:
So it is about 7% in our tests. But as you probably know, there is no real reason to keep those vars around.
Magic methods are slower than regular ones?
I love to use value objects. And in those objects, I normally use __toString() to cast the object to a string. But I've had some remarks that you should just make them yourself to have a speed boost. Time to take a look at that.
Turns out magic methods are indeed a tiny bit slower, at about 12% in this test.
Final classes should be faster than non-final classes?
A friend of mine (the very talented Wouter Sioen) declares his classes final on the creation and only changes it when they really need to be extended.
I'm pretty sure he does that due to OOP reasons, but maybe it's also a bit faster. That could make sense right?
Turns out it does
In our tests, it is slightly faster to use final
That said, I think it a good thing to do anyway.
Do comments have an impact on your code?
Ok, this is the last one. This has brought so many discussions in the past. Docblocks over return types, code should be self-documenting, ... You've seen the discussions before.
All of those Katy Perry facts result in:
About these tests
Some of these tests might surprise you, some might not. That said, please don't stare yourself blind at the results here. Speed is just one part of software development, and I personally think marginal gains don't out weight good developer practices.
At least you left here with some fun facts about pop stars.