A Really Basic Swoole Threading Example
The first thing I wanted to try out when starting with Swoole, is some basic threading to see what kind of performance increase one could expect.
Related Posts
Single Threaded Example:
Below is a single-threaded example of printing out the prime numbers that exist between a pair of numbers. The functions have been set as variables so that this example and the threaded example are as close as possible.
<?php
$timeStart = microtime(true);
$isPrime = function($n) {
for ($x=2; $x<$n; $x++)
{
if ($n %$x ==0)
{
return false;
}
}
return true;
};
$findPrimeNumbers = function($start, $end) use($isPrime){
for ($i=$start; $i <= $end; $i++)
{
if ($isPrime($i))
{
print "$i is a prime number" . PHP_EOL;
}
}
};
$numThreads = 6;
$start = 10000000;
$end = 10010000;
$findPrimeNumbers($start, $end);
$timeEnd = microtime(true);
$timediff = $timeEnd - $timeStart;
print "That took " . $timediff . " seconds" . PHP_EOL;
Swoole Multithreaded Example:
Below is a multi-threaded example whereby I split the range of numbers into sub-chunks for the threads to loop over and fetch the prime numbers for. Now there isn't one range, but 6 smaller ones.
<?php
$timeStart = microtime(true);
$isPrime = function($n) {
for ($x=2; $x<$n; $x++)
{
if ($n %$x ==0)
{
return false;
}
}
return true;
};
$findPrimeNumbers = function($start, $end) use($isPrime){
for ($i=$start; $i <= $end; $i++)
{
if ($isPrime($i))
{
print "$i is a prime number" . PHP_EOL;
}
}
};
$numThreads = 6;
$start = 10000000;
$end = 10010000;
$range = $end - $start;
$chunkSize = intval($range / $numThreads);
for ($i=0; $i<$numThreads; $i++)
{
$threadStart = $start + ($i * $chunkSize);
$threadEnd = $threadStart + $chunkSize;
print "Allocating thread to $threadStart - $threadEnd" . PHP_EOL;
$processes[$i] = new \Swoole\Process(function () use ($findPrimeNumbers, $threadStart, $threadEnd) {
$findPrimeNumbers($threadStart, $threadEnd);
});
$processes[$i]->start();
}
for ($i=0; $i<$numThreads; $i++)
{
\Swoole\Process::wait(true);
}
$timeEnd = microtime(true);
$timediff = $timeEnd - $timeStart;
print "That took " . $timediff . " seconds" . PHP_EOL;
Results
Below are the results comparing a the single-threaded performance against running on all 6 cores of my Ryzen 3500x.
The single-threaded example took 12.42 seconds to complete, whilst the traditional single-threaded logic took 61.08 seconds. This means that spreading the workload over 6 threads made the application go 4.23 times faster.
First published: 26th June 2021