PHP8のパフォーマンスについて

2020年11月26日に、PHP8がリリースされました。

PHP8では実行時(JIT)コンパイラーが導入されているため、リクエストがくるとソースコードがネイティブコードに変換されます。
もう一度同じ処理がリクエストされると、そのネイティブコードをそのまま実行することで処理が高速化され、1.5~2倍の処理速度向上が見込めるとのことです。

今回は、コンテナでCentOS7をベースにPHP8を入れて使ってみたいと思います。
※普段は、alpineを利用していますが、時間短縮のためパッケージとしてPHP8が用意されていたのがCentOSを利用してます。

php-fpmコンテナ(CentOS)

phpとphp-fpmを稼働させるコンテナのため、以下2つのファイルを作成します。

Dockerfile

FROM centos:7

RUN yum -y update && yum clean all
RUN yum -y install epel-release
RUN yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

RUN yum -y --enablerepo=remi,remi-php80 install php php-mbstring php-pdo php-mysqlnd php-gd php-xml php-fpm pphp-crypt php-pear php-common php-pecl-zip php-process php-cli php-devel

RUN mkdir /run/php-fpm
RUN useradd -u 105 -U nginx && \
    groupmod -g 105 nginx

COPY ./php/www.conf /etc/php-fpm.d/www.conf

EXPOSE 9000

CMD ["php-fpm", "-F"]

phpとphp-fpmが稼働する、最低限の内容としています。

以下、各行の内容となります。

3行目

RUN yum -y update && yum clean all

OSのシステムアップデートなどを行います。

4~5行目

RUN yum -y install epel-release
RUN yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

CentOSで利用可能なリポジトリ、epelとremiを追加します。

7行目

RUN yum -y --enablerepo=remi,remi-php80 install php php-mbstring php-pdo php-mysqlnd php-gd php-xml php-fpm pphp-crypt php-pear php-common php-pecl-zip php-process php-cli php-devel

追加したリポジトリより、PHP8をインストールします。
幾つか、不要かもしれない内容が含まれているかも・・・しれません。

ちなみにインストール可能な内容は、以下のURLから確認が可能です。
https://rpms.remirepo.net/enterprise/7/php80/x86_64/repoview/

9~10行目

RUN mkdir /run/php-fpm
RUN useradd -u 105 -U nginx && \
    groupmod -g 105 nginx

php-fpmが稼働する際に必要なディレクトリと、php-fpmの実行ユーザー/グループを作成(変更)しています。

12行目

COPY ./php/www.conf /etc/php-fpm.d/www.conf

php-fpmの設定ファイルをコピーします。
※ここは、docker-compose側で指定の方が楽かもしれない。

14行目

EXPOSE 9000

コンテナで利用するポートは、php-fpmで利用する9000ですので、こちらを指定しておきます。

16行目

CMD ["php-fpm", "-F"]

php-fpmをフォアグラウンドで実行させます。

www.conf

[www]
listen = 9000

listen.owner = nginx
listen.group = nginx
listen.mode = 0666

user = nginx
group = nginx

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on

php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session

変更している箇所は、listenやuser、groupのあたりとなります。

IPは指定せずポートだけで待ち受けるため、listenについては9000とポートだけを指定する様にしています。

また、userとgroupについても、コンテナ作成時に作られるnginxを指定しています。

Nginxコンテナ

Nginxのコンテナについては、ほぼイメージのままで利用します。

最終的に、docker-composeで2つのコンテナをアップするので、その際に利用する、default.conf だけ先に作成しておきます。

default.conf

server {
    listen 80;
    server_name _;

    root  /var/www/html;
    index index.php index.html;

    access_log /var/log/nginx/access.log ltsv;
    error_log  /var/log/nginx/error.log;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(\.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

docker-composeファイルを用意する

Nginxとphp-fpm、2つのコンテナをアップするためのdocker-compose.ymlを作成します。

version: "2"

services:
  nginx:
    image: nginx:1.19-alpine
    container_name: nginx
    restart: always
    ports:
      - 80:80
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./data:/var/www
    links:
      - php-fpm
    depends_on:
      - php-fpm
  php-fpm:
    build: ./php-fpm
    container_name: php-fpm
    restart: always

Nginxをアップする際に、先ほど作成したdefault.confを上書きする様に、volumesに指定をしておきます。

コンテナを起動する

起動する前に、buildを行います。

docker-compose build

buildが完了したら、以下のコマンドでコンテナを起動します。

docker-compose up -d

コンテナが起動したら、動いているかを見てみます。

docker-compose ps

コマンドを実行すると、以下のように表示されるはずです。

nginx /docker-entrypoint.sh ngin … Up 0.0.0.0:80->80/tcp
php-fpm php-fpm -F Up 9000/tcp

起動したコンテナで、PHP8が動いているか確認してみました。

ちゃんと動いている様です・・・。

PHP8のパフォーマンスを確認する

コンテナを立ち上げるところまでは無事終わったので、どのくらいパフォーマンスに違いがあるのかを確認したいと思います。

比較に利用させてもらったのは、以下のページのものとなります。

PHPコードの処理速度を比較するためのベンチマーク計測用関数を自作する
https://wemo.tech/1486

記載されていたコードを、data/html/以下にtest.phpとして設置しました。

また、比較のため開発環境として利用している、Nginx+PHP7.3でも同様の内容を実行してみました。

PHP7 環境

  • AlpineLinux + Nginx(1.19)
  • AlpineLinux + php-fpm(php7.3)

PHP8 環境

  • AlpineLinux + Nginx(1.19)
  • CentOS + php-fpm(php8.0)

実行結果

PHP7

1回目:0.0003364086秒
2回目:0.0003226990秒
3回目:0.0003410038秒
4回目:0.0003613277秒
5回目:0.0003455382秒

PHP8

1回目:0.0002960610秒
2回目:0.0002974842秒
3回目:0.0002891736秒
4回目:0.0002942722秒
5回目:0.0002822718秒

総括

まさか、ただのループ処理だけでこんなに違いがでるなんて・・・想像もしてなかったため、複雑な処理やDB接続などもっと違う処理やWordPress、各種フレームワークでのベンチも、時間を見つけて取りたいと思います。

また、AlpineLinuxでもPHP8を利用できるよう、環境を作っていく予定です。

関連する記事