4 PHP Tricks to Boost Script Performance
Tags: php, webdev, programming, performance
Published: 2020-04-14 12:07:57

Normally I write code by using the conventional, obvious PHP functions to solve corresponding problems. But for some of these problems I came across alternative solutions that especially increase performance.

In this article I want to present some of these alternatives. This is useful, if you're searching for possibilities to decrease execution time even more in production. Let's see, which PHP methods might be replaced by a more performant approach and if there is any cost or trade-off.

ℹ *All these methods were tested with PHP 7.4 on a local web server*

## 1. Removing duplicates

You have a large array with duplicates and want to remove them to only have an array with unique values only.

### 🐌 Conventional

```php
array_unique($array);
```

### ⚡ Alternative

```php
array_keys(array_flip($array));
```

### ⏲ Performance

I created an array with more than 4 million elements having more than 3 million duplicates. Here is the top result:

| method | execution time |
|--------|---------------:|
| `array_unique` | 787.31 ms |
| `array_keys` `array_flip` | 434.03 ms |

The alternative approach is **1.8x** (44.87%) faster in this measurement. On average, it was ~1.5x (30%) faster. Trade-off: This is only applicable for simple, one-dimensional arrays since `array_flip` replaces keys by values.

## 2. Get random array element

You have a large array and want to pick a random value from it.

### 🐌 Conventional

```php
array_rand($array);
```

### ⚡ Alternative

```php
$array[mt_rand(0, count($array) - 1)];
```

### ⏲ Performance

I created an array with 5 million elements. Here is the top result:

| method | execution time |
|--------|---------------:|
| `array_rand` | 25.99 μs |
| `mt_rand` | 0.95 μs |

The alternative approach is **27.3x** (96.33%) faster in this measurement. On average, it was ~8x (87%) faster. This result is particularly surprising, as `mt_rand` is the implementation of the Mersenne Twister Random Number Generator and since PHP 7.1, the internal randomization algorithm [has been changed](https://www.php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-srand-aliases) to use exactly that same algorithm.

## 3. Test for alphanumeric characters

You have a string and want to test, if it only contains alphanumeric characters.

### 🐌 Conventional

```php
preg_match('/[a-zA-Z0-9]+/', $string);
```

### ⚡ Alternative

```php
ctype_alnum($string);
```

### ⏲ Performance

I created an array with more than 100k alphanumeric and non-alphanumeric strings. Here is the top result:

| method | execution time |
|--------|---------------:|
| `preg_match` | 15.39 ms |
| `ctype_alnum` | 2.06 ms |

The alternative approach is **7.5x** (86.59%) faster in this measurement. On average, it was ~4x (76%) faster.

The same can be applied to `ctype_alpha()` (check for alphabetic characters) and `ctype_digit()` (check for numeric characters).

## 4. Replace substrings

You have a string and want to replace a part of it by another substring.

### 🐌 Conventional

```php
str_replace('a', 'b', $string);
```

### ⚡ Alternative

```php
strtr($string, 'a', 'b');
```

### ⏲ Performance

I created an array with 5 million random strings. Here is the top result:

| method | execution time |
|--------|---------------:|
| `str_replace` | 676.59 ms |
| `strtr` | 305.59 ms |

The alternative approach is **2.2x** (54.83%) faster in this measurement. On average, it was ~2x (51%) faster.

## Additional performance improvements

Here are some additional points I integrated into my coding convention that I found to improve perfomance slightly (if applicable):

- Prefer JSON over XML
- Declare variables before, not in every iteration of the loop
- Avoid function calls in the loop header (in `for ($i=0; $i<count($array); $i)` the `count()` gets called in every iteration)
- Unset memory consuming variables
- Prefer select statement over multiple if statements
- Prefer require/include over require_once/include_once (ensure proper opcode caching)

Some final words: I know the discussion about premature optimization. And I agree that performance in production is depending on bottlenecks like database queries which should be focused on when dealing with performance. But I think, if there are alternatives that are faster and e.g. in case of regex easier to handle and maintain, why not using them?

## Wrap it up

We've seen, that even with the current PHP 7.4 (which is already a lot faster than previous PHP versions) there are possibilities to boost script performance with alternative approaches even more. If you want to verify the figures presented in this article yourself, I created a repository with all tests:

{% github devmount/faster-php no-readme %}

I used [this great tool](https://github.com/bvanhoekelen/performance) by Bart van Hoekelen to measure execution time.

Please don't hesitate to comment here or [create an issue](https://github.com/devmount/faster-php/issues/new)/PR at the repo above if you know additional ways to improve performance of certain PHP functions.

---

*Published: 14th April 2020*