DEV Community

Kristjan Siimson
Kristjan Siimson

Posted on • Updated on

3 tips for performant PHP code

Disclaimer

This is an advanced post about performance optimization. Don't blindly take this advice. Not all projects prioritize performance. If you are not familiar with the mentioned language features, take your time to understand them.

(1) Know your language constructs

Example

isset($array['key']) over array_key_exists('key', $array)

Reasoning

Faster than function calls. There are two language constructs that particularly useful, which are isset() and empty().

[Pitfalls] empty() uses type juggling, see next section.

Opcodes

if(isset($array['key'])) {}

op return operands
ISSET_ISEMPTY_DIM_OBJ ~1 !0, 'key'
JMPZ ~1, ->2

if(array_key_exists('key', $array)) {}

op return operands
INIT_FCALL 'array_key_exists'
SEND_VAL 'key'
SEND_VAL !0
DO_ICALL $2
JMPZ $2, ->5

(2) Don't fight the type system (but learn it first)

Example

if($arr) {} over if(count($arr) > 0) {}

Reasoning

Using type juggling reduces redundant opcodes, and therefore also memory allocations.

[Pitfalls] PHP Magic Tricks: Type Juggling presentation by Insomnia Security outlines some example security exploits enabled by inappropriate use of type juggling. Perhaps the most surprising behavior is exhibited in string to integer conversion, e.g. "0e768261251903820937390661668547" == "0". This is intentional and well documented.

Opcodes

if($arr) {}

op return operands
JMPZ !0, ->1

if(count($arr) > 0) {}

op return operands
COUNT ~1 !0
IS_SMALLER ~2 0, ~1
JMPZ ~2, ->3

(3) Clean up your variables

PHP does some nifty behind-the-scenes optimizations, and this tip is to let it do it’s job. One of the tricks PHP does is related to passing variables by value, rather than reference. PHP will optimize away assignments if the value is not assigned to any other variable, and the value doesn't change.

First example ✔️ -

<?php
$var = 'a';
function a($value) {
    echo $value; // do something
}
a($var);

Here the value is assigned in the variable assignment. Even though the value is passed by value, there is actually only one assignment, because the value doesn't change.

Second example ⚠️ -

<?php
$var = b;
function a($value) {
    $value = 'a';
    echo $value; // do something
}
a($var);

Here the value changes and therefore there are two assignments, one in the main scope and another inside the function.

Third example ✔️ -

function a($value) {
    $value = 'a';
    echo $value; // do something
}
a('b');

In this example, the value is assigned just before calling a(), and since nothing holds reference to it, PHP can mutate the value, instead of making another assignment.

Reasoning

This is not something to worry so much about when the values are small, but I’ve caught some OOM situations where the root cause was an useless variable. This also helps the garbage collector, which only cleans up the values that are not referenced by any variables.

Top comments (4)

Collapse
 
klnjmm profile image
Jimmy Klein • Edited

I don't agree with some of your points :

  • isset($array['key']) over array_key_exists('key', $array)

isset don't have the same result than array_key_exists. It also test than the value at the key is null. So be careful, you have to know exactly what test you want.
(see my post dev.to/klnjmm/5-bad-habits-to-lose...)

  • > Faster than function calls. There are two language constructs that particularly useful, which are isset and empty.

I don't recommend to use empty. It can cause a lot of bugs because empty test that a variable is false. And a lot of values in PHP is considered as false : null, 0, "", false, [], ...etc.
Instead consider using one of this (you have to know the type of you variable)

if ($var !== null) {}
if ($var !== '') {}
...

Avoid using empty function !

  • if($arr) {} over if(count($arr) > 0) {}

if($arr) {} makes an implicit cast of $arr (same problem than empty function).
If you know that $arr is an array, I prefer count method or if ($arr !== [])

Collapse
 
siimsoni profile image
Kristjan Siimson

Well, it is your job as a programmer to know when you use which language feature. You can't argue that a function is bad because you can use it incorrectly.

Collapse
 
klnjmm profile image
Jimmy Klein

Ok but I think that recommend to other readers (and maybe beginners) to use empty function is not a good thing.

Thread Thread
 
siimsoni profile image
Kristjan Siimson • Edited

True, I've added a disclaimer in beginning of the article.

EDIT: And explained the potential pitfalls associated with these optimizations.