Programster's Blog

Tutorials focusing on Linux, programming, and open source

Install PHP 7.0 With Pthreads on Ubuntu 16.04

PHP can support multithreading for compute intensive workloads. The tutorial below is divided into two parts. The first part will recompile PHP 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.

Requirements

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

Video Walkthrough

Compile PHP

The first thing we need to do is compile our own version of PHP that will be able to support the installation of the pthreads extension.

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 

Install pear for installing pthreads later.

sudo apt-get install php7.0-dev php-pear -y

The previous command will have installed PHP, so remove it

sudo apt-get remove php-cli -y

Go to your home directory. We will perform all of our work in here.

cd $HOME

Go to the releases page and grab the .tar.gz link for the latest release for the version of PHP you want. By the time you read this tutorial, these versions are likely to be out of date but serve as a working example.

wget https://github.com/php/php-src/archive/php-7.0.26.tar.gz

Extract the source code and rename it to php-src so the rest of the steps in this tutorial work no matter what version you are running.

tar --extract --gzip --file php-*
rm php-*.tar.gz
mv php-src-* php-src
cd $HOME/php-src
./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

The important parts for pthreads are --enable-maintainer-zts and --enable-debug.

Build PHP.

make && sudo make install

Update the symlink for php to point to our custom build.

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

Testing PHP Installation

You have now compiled PHP 7.0 from source with the necessary configuration necessary for installing pthreads later.

You can check your version by running:

php -v

You can also check that you have ZTS support which is required for pthreads:

php -a
echo PHP_ZTS; // this should output a 1 and not a 0

Install Pthreads

You have completed the first step of the tutorial which is to build your own version of PHP that will support installing pthreads. Now it is time to actually add the extension.

Use PECL to install the pthreads extesion

sudo pecl install pthreads

PHP.INI

At the end of the previous step, the console will have told you that you need to add extension=pthreads.so to your php.ini file. However, we don't have one yet for our custom built PHP so lets create it.

sudo mkdir -p /etc/php7/cli/
sudo cp /usr/lib/php/7.0/php.ini-production.cli /etc/php7/cli/php.ini

Now add the pthreads extension to the php ini file ( and opcache whilst we're in there).

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

Testing Threading Support

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