Concurrency in PHP

Sina Ahamadpour
4 min readMar 3, 2024

--

As a person who fell in love with PHP, worked with PHP for almost 10 years, and moved to another country as a Software Engineer where most of his experience was in PHP, I always envy other languages that have proper tooling for Concurrency!

I’m not sure if one day PHP can get there and I assume this is not something that it is aiming for probably! I have to admit that I enjoyed working with Promises in Javascript. I loved how concurrency was baked in Go with channels, select, goroutines, and other stuff. So when I’m working with PHP I feel a bit off because of that.

In 2024 things seem to be different, I’m pretty keyed up about all the collaborations and tools that have been added to the PHP Community and its projects. The language seems to be more stable, the toolings seem to be more mature and many companies including startups and enterprise companies are built on top of PHP. About startups: I can not think of any other good option for shaping the product than PHP Frameworks!

Things that I think added great value and worth to be checked

What is Concurrency?

In computer science, concurrency is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order, without affecting the outcome.

- Wikipedia

Imagine you are working with a CLI script which is doing time-consuming tasks that can be split into smaller tasks. This can be calling multiple REST endpoints, saving and reading things into databases, file system changes, or any other task. Normally in PHP code is running line by line and the main thread always does one thing at a time. We don’t have this forking and joining child threads to main threads by default but we can utilize a small composer package to achieve that. All you need to do is add the spatie/fork package to your project. This package requires pcntl and sockets modules to work. Make sure you have it inside your project.

If you run php -m in your terminal, you must see these modules as below:

Time for coding

Imagine you have this function that is slow and you are dependent on its result, All it does is count from 0 to 100M.

function timeConsumingFunction($to = 100000000): int
{
$sum = 0;
for ($i = 0; $i < $to; $i++) {
$sum++;
}

return $sum;
}

Normally we write something like this:

echo array_sum(
[
timeConsumingFunction(),
timeConsumingFunction(),
timeConsumingFunction(),
]
);

How long does it take? Let’s benchmark the time:

$start_time = microtime(TRUE);

echo "Result: " . array_sum(
[
timeConsumingFunction(),
timeConsumingFunction(),
timeConsumingFunction(),
]
);

$end_time = microtime(TRUE);

echo PHP_EOL . "Time: " . $end_time - $start_time;

As you can see in the below output it takes about 4s, This can vary based on the computational power, memory, and …. Your task can be CPU-intensive, I/O intensive, or memory-intensive. Our simple example is CPU intensive.

Now let’s write the code in a different way using Fork!

$start_time = microtime(TRUE);

$results = \Spatie\Fork\Fork::new()->run(
function () {
return timeConsumingFunction();
},
function () {
return timeConsumingFunction();
},
function () {
return timeConsumingFunction();
}
);

echo "Result: " . array_sum($results);

$end_time = microtime(TRUE);

echo PHP_EOL . "Time: " . $end_time - $start_time;

In this example, we used the \Spatie\Fork\Fork which allows us to create three different tasks and aggregate the result of each one.

Let’s see the result:

As you can see we have decreased the time from 4.3s to 1.5s 🎉

Where to go?

I highly recommend checking the spatie/fork GitHub page. It has clear instructions for developers. I believe this is one of the great open-source packages made by Spatie.

You should also check this video:

This was just a simple article to talk about concurrency in PHP, there are tons of good stuff on the internet which I recommend reading if you like the concept.

Have a great day!

--

--