Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Ubuntu 16.04 - Compile PHP 7.2 with pthreads

PHP can support multithreading for compute intensive workloads. This tutorial will recompile PHP from source with ZTS enabled in order to allow us to then add the pthreads extension for the PHP CLI (not for Apache or FPM). I will not dive into when not to use multithreading in PHP, but its fair to say that there are good reasons why it supported for the webserver, and hence the pre-built package that you install from the Ubuntu repositories.

The majority of the content in the answer below came from an answer on Stack Overflow for how to install php7 (zts) + pthreads on Ubuntu 14.04. However I have tweaked it as necessary for Ubuntu 16.04 and without even trying to add FPM support.

Related Posts

Requirements

  • 1GiB Ram - lower than this and your compilation step may fail

Recompile PHP

Download the necessary packages for compilation.

sudo apt update && \
sudo apt install -y libzip-dev bison autoconf build-essential pkg-config git-core \
libltdl-dev libbz2-dev libxml2-dev libxslt1-dev libssl-dev libicu-dev \
libpspell-dev libenchant-dev libmcrypt-dev libpng-dev libjpeg8-dev \
libfreetype6-dev libmysqlclient-dev libreadline-dev libcurl4-openssl-dev 

Go to your home directory. And download the PHP source code that we will compile PHP from.

cd $HOME
wget https://github.com/php/php-src/archive/php-7.2.2.tar.gz
tar --extract --gzip --file php-7.2.2.tar.gz
cd $HOME/php-src-php-7.2.2
./buildconf --force
CONFIGURE_STRING="--prefix=/etc/php7 --with-bz2 --with-zlib --enable-zip --disable-cgi \
   --enable-soap --enable-intl --with-openssl --with-readline --with-curl \
   --enable-ftp --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd \
   --enable-sockets --enable-pcntl --with-pspell --with-enchant --with-gettext \
   --with-gd --enable-exif --with-jpeg-dir --with-png-dir --with-freetype-dir --with-xsl \
   --enable-bcmath --enable-mbstring --enable-calendar --enable-simplexml --enable-json \
   --enable-hash --enable-session --enable-xml --enable-wddx --enable-opcache \
   --with-pcre-regex --with-config-file-path=/etc/php7/cli \
   --with-config-file-scan-dir=/etc/php7/etc --enable-cli --enable-maintainer-zts \
   --with-tsrm-pthreads --enable-debug --enable-fpm \
   --with-fpm-user=www-data --with-fpm-group=www-data"

./configure $CONFIGURE_STRING

Build PHP.

make && sudo make install

Add Pthreads

We are going to manually compile and add pthreads to PHP, so make the phpize and php-config helper programs executable

sudo chmod o+x /etc/php7/bin/phpize
sudo chmod o+x /etc/php7/bin/php-config
git clone https://github.com/krakjoe/pthreads.git

At this point, I would like to switch to a tagged release of pthreads, but that doesn't work yet.

Run phpize on pthreads.

cd pthreads
/etc/php7/bin/phpize

Set configuration options for pthreads. --enable-pthreads=shared is the main aspect of the configuration

./configure \
--prefix='/etc/php7' \
--with-libdir='/lib/x86_64-linux-gnu' \
--enable-pthreads=shared \
--with-php-config='/etc/php7/bin/php-config'

Build and install the extension

make && sudo make install

Now create the php ini file.

cd $HOME/php-src-php-7.2.2
sudo mkdir -p /etc/php7/cli/
sudo cp php.ini-production /etc/php7/cli/php.ini

Add the pthreads extension to the ini file.

echo "extension=pthreads.so" | sudo tee -a /etc/php7/cli/php.ini
echo "zend_extension=opcache.so" | sudo tee -a /etc/php7/cli/php.ini

Remove any link to PHP if it already exists. If this was a server from scratch and you only ran the steps in this tutorial, this step should do nothing.

sudo rm /usr/bin/php

Link to our newly compiled PHP binary.

sudo ln -s /etc/php7/bin/php /usr/bin/php

Testing

You can check which version of PHP you have installed by running:

php --version

Multithreading Test

In order to test that multithreading was now available in the PHP CLI, I tweaked a script from a tutorial on Sitepoint and put it below

<?php

class Task extends Threaded
{
    private $value;

    public function __construct(int $i)
    {
        $this->value = $i;
    }

    public function run()
    {
        $s=0;

        for ($i=0; $i<10000; $i++)
        {
            $s++;
        }

        echo "Task: {$this->value}\n";
    }
}

# Create a pool of 4 threads
$pool = new Pool(4);

for ($i = 0; $i < 15000; ++$i) 
{
    $pool->submit(new Task($i));
}

while ($pool->collect());

$pool->shutdown();

As you can see below, when I run the script, I have 5 PHP threads, one from the main thread, and then the 4 workers in the pool that I created.

Conclusion

We now have support for multithreading in PHP on Ubuntu 16.04. If you wish to learn more about how to make use of pthreads, I recommend reading "Parallel Programming with Pthreads in PHP – the Fundamentals" and the man pages of course.

References