LoginSignup
9
5

More than 3 years have passed since last update.

【PHP】parallelでマルチスレッドを試そう

Last updated at Posted at 2021-02-07

はじめに

PHPは、プログラムを上から順に実行するシングルスレッドの言語です。
今回は、parallelという拡張モジュールを使うことで、PHPでマルチスレッドを扱える!』そうなので、試したいと思います💡

parallelとは

  • PHP拡張モジュール
  • PHP 7.2以降で動作
  • PHP ZTS版でのみ動作
  • Webからのリクエストにも対応
  • 導入が少々手間

※マルチスレッドと言えばpthreadsが使われているそうですが、「この拡張機能はメンテナンスされておらず、終了していると考えられます。」と書かれています。PHP 7.4以降は、サポートしていないということみたい。。

準備

使用技術

  • Docker

ディレクトリ構成

.
├── Dockerfile
└── src
    └── index.php

srcの中をホストと共有するような構成にしています。

コンテナ作成

Dockerfile

FROM php:7.4-zts 

RUN apt-get update

RUN pecl install parallel \
    && docker-php-ext-enable parallel

WORKDIR /var/www/html

Docker Hubにイメージをプッシュしてあるので、詳しくはそちらをご参照ください。

  • ztsは、「ZTS (Zend Thread Safety) 」のことで、要はマルチスレッドを安全に扱うモードです。
  • peclコマンドを使って、parallelをインストールしています。PECLは、「PHPの拡張モジュールを提供してくれるサービス」です。
  • parallelを有効化しています。

CLI上で実行

$ docker build --no-cache=true -t my_php:latest .

上記のDockerfileからイメージを作成します。

$ docker image ls
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
my_php        latest    ff3880c9f1c9   41 seconds ago   407MB

イメージが作成されているか確認できました。

docker run -itd --rm -v $PWD/src:/var/www/html/ --name my_php my_php:latest /bin/bash

dockerのコンテナを作成することができます。

$ docker exec -it my_php bash

root@0e826bad2d7d:/var/www/html# php -v
PHP 7.4.15 (cli) (built: Feb  4 2021 17:37:54) ( ZTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

root@0e826bad2d7d:/var/www/html# php -m
〜〜略〜〜
parallel
〜〜〜〜〜

root@0e826bad2d7d:/var/www/html# pecl list -a
〜〜略〜〜
Installed packages, channel pecl.php.net:
=========================================
Package  Version State
parallel 1.1.4   stable

コンテナの中に、コマンドを実行してみました。ちゃんと、parallelが入ってることを確認できました🥳

マルチスレッドのコード

サンプル1

index.php
<?php

$runtime = new \parallel\Runtime();

$runtime->run(function(){
    echo '★';
});

for ($i = 0; $i < 100; $i++) {
    echo '.';
}

$runtime->run()で新たなプロセスが実行されます。

root@0e826bad2d7d:/var/www/html# php index.php
..................................................★..................................................
root@0e826bad2d7d:/var/www/html# php index.php
...........................................................★.........................................
root@0e826bad2d7d:/var/www/html# php index.php
.....................★...............................................................................
root@0e826bad2d7d:/var/www/html# php index.php
...........★.........................................................................................
root@0e826bad2d7d:/var/www/html# php index.php
....................................................................................................★

が出力されるタイミングがバラバラです。つまり、メインのスレッドとは別のスレッドを立ち上がり、出力していることを意味します。

サンプル2

index.php
<?php

$runtime = new \parallel\Runtime();

$runtime->run(function(){
    sleep(1);
    echo 'サブ', PHP_EOL;
});

echo 'メイン', PHP_EOL;

root@0e826bad2d7d:/var/www/html# php index.php
メイン
サブ

1秒経ってから、「サブ」が出力されます。このことからもメインルーチンとは別のスレッドで動いていることがわかります。

Webからの実行

  • Docker Compose

ディレクトリ構成

.
├── docker-compose.yml
├── nginx
│   └── default.conf
├── php
│   └── Dockerfile
└── src
    └── index.php

php

dockerfile
FROM mohsenmottaghi/php-fpm-zts:7.4

RUN pecl install parallel \
    && docker-php-ext-enable parallel

WORKDIR /var/www/html

先程とは、違うベースイメージを使用しています。

nginx

default.conf
server {
    listen 80;
    root  /var/www/html;
    index index.php index.html;
    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;
    location ~ \.php$ {
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass   app:9000;
          fastcgi_index  index.php;
          include        fastcgi_params;
          fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param  PATH_INFO $fastcgi_path_info;
      }
}

コード

index.php
<?php

$runtime = new \parallel\Runtime();

$runtime->run(function(){    
    echo '★';
});

for ($i = 0; $i < 10000; $i++) {
    if ($i % 200 === 0) echo "\n";
    echo '.';
}

docker-compose up -dを実行し、localhost:8000にアクセスすると確認できます。
スクリーンショット 2021-02-14 0.01.57.png

終わりに

もっと色々なことができるそうですが、まずはお試しでということで😌
pthreadsとは違い、Webからのリクエストでも動作するので、今後の発展に期待ですね!!!

ps. @sj-i さん、コメントいただきありがとうございました!

参考

9
5
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5