Amazon Linux 2のPHP 7.4環境に、OPcacheを導入する

# What's？

PHPソースコードのコンパイル結果をキャッシュして、高速化するにはOPcacheということで。

PHP 7.4環境にOPcacheを導入してみます。

# OPcache

OPcacheについてのドキュメントは、こちら。

https://www.php.net/manual/ja/book.opcache.php

「はじめに」に説明が書かれています。

> OPcache はコンパイル済みのバイトコードを共有メモリに保存し、PHP がリクエストのたびにスクリプトを読み込み、パースする手間を省くことでパフォーマンスを向上させます。 

https://www.php.net/manual/ja/intro.opcache.php

このOPcacheを導入してみます。

# 環境

今回の環境は、Amazon Linux 2です。

```shell
$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"

$ uname -srvmpio
Linux 4.14.252-195.483.amzn2.x86_64 #1 SMP Mon Nov 1 20:58:46 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
```

PHP 7.4は、`amazon-linux-extras`でインストールしたものを使います。

```shell
$ sudo amazon-linux-extras install php7.4
```

バージョン。

```shell
$ php --version
PHP 7.4.21 (cli) (built: Jul  7 2021 17:35:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```

Webサーバーは、Apacheで。PHP-FPMとの連携は設定済みとします。

```shell
$ httpd -V
Server version: Apache/2.4.51 ()
Server built:   Oct  8 2021 22:03:47
Server's Module Magic Number: 20120211:118
Server loaded:  APR 1.7.0, APR-UTIL 1.6.1
Compiled using: APR 1.7.0, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_PROC_PTHREAD_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/httpd"
 -D SUEXEC_BIN="/usr/sbin/suexec"
 -D DEFAULT_PIDLOG="/run/httpd/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"
```

# OPcacheをインストールする

「はじめに」を見ると、OPcacheはPECLでインストールできそうなことが書かれています。

>  PHP 5.2, 5.3, 5.4 では » PECL で利用可能です。

https://www.php.net/manual/ja/intro.opcache.php

で、PECLのサイトに行っていると、すでにメンテナンスされていないことがわかります。

> This package is not maintained anymore and has been superseded. Package has moved to channel http://php.net/opcache

https://pecl.php.net/package/ZendOpcache

で、案内されている`http://php.net/opcache`にいくと、最初に見たOPcacheのドキュメントにたどり着きます。

つまり、ループします…。

インストール手順にも、インストール方法自体は書かれていないのですが

https://www.php.net/manual/ja/opcache.installation.php

今回の環境においては、`yum`でインストールすることができます。

```shell
$ yum info php-opcache
読み込んだプラグイン:langpacks, priorities, update-motd
利用可能なパッケージ
名前                : php-opcache
アーキテクチャー    : x86_64
バージョン          : 7.4.21
リリース            : 1.amzn2
容量                : 318 k
リポジトリー        : amzn2extra-php7.4/2/x86_64
要約                : The Zend OPcache
URL                 : http://www.php.net/
ライセンス          : PHP
説明                : The Zend OPcache provides faster PHP execution through opcode caching and
                    : optimization. It improves PHP performance by storing precompiled script
                    : bytecode in the shared memory. This eliminates the stages of reading code from
                    : the disk and compiling it on future access. In addition, it applies a few
                    : bytecode optimization patterns that make code execution faster.
```

インストール。

```shell
$ sudo yum install php-opcache
```

PHPのバージョン情報に、`with Zend OPcache`という表記が現れるようになります。

```shell
$ php --version
PHP 7.4.21 (cli) (built: Jul  7 2021 17:35:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.21, Copyright (c), by Zend Technologies
```

OPcacheに含まれるファイルは、こちら。

```shell
$ rpm -ql php-opcache
/etc/php-zts.d/10-opcache.ini
/etc/php-zts.d/opcache-default.blacklist
/etc/php.d/10-opcache.ini
/etc/php.d/opcache-default.blacklist
/usr/lib64/php-zts/modules/opcache.so
/usr/lib64/php/modules/opcache.so
```

インストールされた設定ファイルを見てみましょう。

```shell
$ grep -vE '^;|^$' /etc/php.d/10-opcache.ini
zend_extension=opcache
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.blacklist_filename=/etc/php.d/opcache*.blacklist
opcache.huge_code_pages=1
```

ここで、推奨設定を見るといくつか項目が足りません。

[推奨される php.ini の設定](https://www.php.net/manual/ja/opcache.installation.php#opcache.installation.recommended)

まずは、`opcache.revalidate_freq`。

各種設定項目の意味は、こちらに書かれています。

https://www.php.net/manual/ja/opcache.configuration.php

デフォルト値は2らしいので、推奨設定に合わせて60にします。

```ini
; How often (in seconds) to check file timestamps for changes to the shared
; memory storage allocation. ("1" means validate once per second, but only
; once per request. "0" means always validate)
opcache.revalidate_freq=60
```

この設定は、キャッシュしたスクリプトの更新をチェックする間隔です。

つまり、`opcache.revalidate_freq`を長くするとPHPソースコードのチェック処理を省くことができますが、代わりにPHPソースコードが更新されてもこの秒数は反映されないことになります。

推奨設定に載っていた、`opcache.fast_shutdown`という項目は、PHP 7.2で削除されたようです。

PHP-FPMに設定を反映するには、再起動します。

```shell
$ sudo systemctl restart php-fpm
```

確認しましょう。こんなファイルを作成。

```php:/var/www/html/phpinfo.php
<?php

phpinfo();
```

ブラウザで見ると、OPcacheが組み込まれていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/e42b409b-e077-1f51-134b-afce4fc332f8.png)

このまま、アクセスを繰り返していくと、キャッシュのヒット回数やキャッシュしているスクリプトの数などが変化していくのが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/5d6848e5-eb7a-1e24-b5db-ff36eeba0619.png)

これで、OPcacheが導入できました、と。

Let's Fast PHP!!

# 補足

先にも書きましたが、`opcache.revalidate_freq`で指定した秒数は、PHPソースコードがキャッシュされたまま変更が反映されなくなります。

すぐに反映を確認したいような開発環境などでは、間隔を短くするか（そもそもOPcacheを組み込まないか）、PHP-FPMを再起動したりすることになるのかな？と思います。