php

3 tips for performant PHP code

siimsoni

Kristjan Siimson

Posted on July 7, 2020

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.

💖 💪 🙅 🚩
siimsoni
Kristjan Siimson

Posted on July 7, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related