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 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.
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 [email protected]: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
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)
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.
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
htop output