Skip to content

Instantly share code, notes, and snippets.

@lokisho
Last active May 24, 2022 01:49
Show Gist options
  • Save lokisho/8ee9e73c92fdb9bce3ea501e7d5217c7 to your computer and use it in GitHub Desktop.
Save lokisho/8ee9e73c92fdb9bce3ea501e7d5217c7 to your computer and use it in GitHub Desktop.
How to install multithreads (pthreads) for php 7.3 ubuntu 18.04

Tutorial

pthreads allows to use multiple threads when running a php script with php cli.

Important: it only works for php cli, not in a web browser
The reasons for that can be found in the article recommended in Acknowledgments and resources section.
We are following 3 steps.
  • Install php7.3 as usual for our web server applications (if you pretend to use only php cli in your server, you can skip this step).
  • Install a compiled php with zts (https://www.php.net/manual/en/pthreads.requirements.php) that will be used by php cli.
  • Install pthreads extension

Add php 7.3 as usual

Add PHP 7.3 PPA

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update

Install PHP 7.3

sudo apt-get install php7.3

Install extensions, some common extensions

sudo apt install php7.3-cli php7.3-fpm php7.3-json php7.3-pdo php7.3-mysql php7.3-zip php7.3-gd  php7.3-mbstring php7.3-curl php7.3-xml php7.3-bcmath php7.3-json

Restart your web server

# Apache
sudo systemctl restart apache2

# Nginx
sudo systemctl restart nginx

Test with a php file, for example, I created a file phpinfo.php in /var/www/html/phpinfo.php with

<?php 
  phpinfo();
?>

I tested acceding it from a browser.

Compile php with zts for pthreads

Install de packages needed for compiling

sudo apt-get update

sudo apt install autoconf automake bison build-essential curl flex \
  libtool libssl-dev libcurl4-openssl-dev libxml2-dev libreadline7 \
  libreadline-dev libsqlite3-dev libzip-dev libzip4 nginx openssl \
  pkg-config re2c sqlite3 zlib1g-dev

We are going to put our compiled php in another location, in this case ~/bin so we don't override existing php installs

mkdir -p ~/bin/php7-latest/

Clone php repo, in my case, I'll clone it in ~/apps

mkdir ~/apps && cd ~/apps && git clone git@github.com:php/php-src.git

cd php-src

git fetch origin && git checkout -b PHP-7.3.11 origin/PHP-7.3.11

build the configuration

./buildconf --force

configure

./configure --prefix=$HOME/bin/php-latest \
--with-zlib \
--enable-zip \
--with-openssl \
--with-readline \
--with-curl \
--with-pear \
--enable-ftp \
--enable-mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql \
--with-libzip=/usr/lib/x86_64-linux-gnu \
--enable-sockets \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-pcntl \
--enable-bcmath \
--enable-mbstring \
--enable-phpdbg \
--enable-shmop \
--enable-simplexml \
--enable-json \
--enable-hash \
--enable-session \
--enable-xml \
--enable-wddx \
--enable-opcache \
--with-pcre-regex \
--with-config-file-path=/$HOME/bin/php-latest/cli \
--with-config-file-scan-dir=$HOME/bin/php-latest/etc \
--enable-cli \
--enable-maintainer-zts \
--with-tsrm-pthreads \
--enable-debug \
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data

make
make test
make install

After make test I got a test failing


FAILED TEST SUMMARY
------------
Test ftp_ssl_connect() function : error conditions [ext/ftp/tests/ftp_ssl_connect_error.phpt]
=============

It doesn't look like an issue for me, so I continued, but if for some reason you need https://www.php.net/manual/en/function.ftp-ssl-connect.php you may try to fix it and recompile

Copy the php.ini file to the install directory

cp php.ini-development ~/bin/php-latest/lib/

Rename two files.

cd ~/bin/php-latest/etc/  
mv php-fpm.conf.default php-fpm.conf
mv php-fpm.d/www.conf.default php-fpm.d/www.conf

Create symbolic links for your for your binary file.

cd ~/bin
ln -s php-latest/bin/php php
ln -s php-latest/bin/php-cgi php-cgi
ln -s php-latest/bin/php-config php-config
ln -s php-latest/bin/phpize phpize
ln -s php-latest/bin/phar.phar phar
ln -s php-latest/bin/pear pear
ln -s php-latest/bin/phpdbg phpdbg
ln -s php-latest/sbin/php-fpm php-fpm

Link your local php to the php command. You will need to logout then log back in for php to switch to the local version instead of the installed version from the default Ubuntu repositories.

# add this to .bashrc or .profile if don't have it
if [ -d "$HOME/bin" ] ; then
  PATH="$HOME/bin:$PATH"
fi

Test our compilation has ZTS enabled

php -r "echo PHP_ZTS . \"\n\";"

expected output: 1

Compile 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 ~/bin/php-latest/bin/phpize
sudo chmod o+x ~/bin/php-latest/bin/php-config

Let's clone pthreads project, I will do it in ~/apps

cd ~/apps
git clone https://github.com/krakjoe/pthreads.git
cd pthreads

Run phpize on pthreads.

~/bin/phpize

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

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

Build and install the extension

make
make test
make install

expected output example

Installing shared extensions:     /home/ubuntu/bin/php-latest/lib/php/extensions/debug-zts-20180731/

Add the pthreads extension to the ini file.

echo "extension=pthreads.so" | tee -a $HOME/bin/php-latest/lib/php.ini-development
echo "zend_extension=opcache.so" | tee -a $HOME/bin/php-latest/lib/php.ini-development

Testing

php -r "echo var_dump(class_exists('Thread'));"

expected output

bool(true)

if failed, check the troubleshooting section bellow.

then I created this file in ~/apps/pthreads_test.php

<?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();

run it with php ~/apps/pthreads_test.php and I got this output in htop (view image in comments)

Troubleshooting

The second time I followed these steps for this tutorial, I had some issues with my php.ini, it was not using the ~/bin/php-latest/lib/php.ini-development.

I run php --ini

Configuration File (php.ini) Path: //home/ubuntu/bin/php-latest/cli
Loaded Configuration File:         (none)
Scan for additional .ini files in: /home/ubuntu/bin/php-latest/etc
Additional .ini files parsed:      (none)

and got that output, so I copied ~/bin/php-latest/lib/php.ini-development to ~/bin/php-latest/etc/php.ini and that solved the problem

After following these steps, I noticed that apache2 stopped and nginx started, taking port 80 and preventing apache2 to restart. It was solved by stopping nginx and starting apache2 again, I would recommend to use only nginx in that case.

Resources & Acknowledments

For this tutorial I took information from

https://askubuntu.com/questions/1102910/how-to-build-php-7-3 https://www.rapidspike.com/blog/php72-pthreads/ http://blog.programster.org/ubuntu16-04-compile-php-7-2-with-pthreads

And I hightly recommend this article to learn how to use pthreads

https://www.sitepoint.com/parallel-programming-pthreads-php-fundamentals/

And of course, the documentation about pthreads https://www.php.net/manual/en/book.pthreads.php

@lokisho
Copy link
Author

lokisho commented Nov 7, 2019

htop output
image

@DanePham
Copy link

Nice solution idol :D But I'm a little confuse about install new module for this "new php-config"
When I install oauth module instead of apt-get install php-oauth .
I have to

wget https://pecl.php.net/get/oauth-2.0.7.tgz 
tar -xvf oauth-2.0.7.tgz
cd oauth-2.0.7
phpize
./configure
make && make install

So do you have short way to install new module php? It'll reduce the time.
Thanks @lokisho, you help me a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment