koudenpaのブログ

趣味のブログです。株式会社はてなでWebアプリケーションエンジニアをやっています。職業柄IT関連の記事が多いと思います。

PHPを運用するときはOPcacheを有効にしておけ

タイトル以上の話はないのだけれど、なんぼか周辺事情を書いておこうと思う。

有効化までのエピソード

昨今のアプリケーションプログラム周りはデフォルト設定が結構いい感じなので、PHP、Laravelのアプリケーションを運用にするにあたって、php.iniの設定はほぼデフォルトママとしていた。

これがまぁなんか妙に遅い。全体的にもっさりしている。

なんでや? と思って「Laravel 高速化」「Laravel チューニング」とかのワードで検索したり、使用しているライブラリの設定リファレンスとか眺めていたのだけれど、全体的になんか遅い、は解消しなかった。

大体やっていることしか書いてなかった。

(読み込むサービスプロバイダの精査とかはしてないけれど、そんなに支配的な影響が出るはずもない)

大分煮詰まってきたので、Laravelではなく、PHPの層でなんかないかと見始めると「OPcacheの有効無効」が怪しそうな雰囲気を醸し出していた。

無効だったので有効にしたら大分早くなった。

具体的には、LaravelのDebugbarでいうところのBootingが200ms位から50ms以下になった。

全リクエストが150ms以上高速化したわけである。デカすぎる。

PHP8に関しては「デフォルト設定が結構いい感じ」ということは多分ないので、php.iniの設定には気を払われたい。

デフォルトはOPcache有効っぽいので、なんか変な設定していたが、他の要因か、細かい設定かも、今や謎。

設定値と動きの様子

世の中の参考になる情報を多少は書いておこうと思う。

日本語のページをググっても、opcacheやJITの仕組みをざっくり解説している記事はあっても、実際の設定や運用の様子が書かれているものはあまり見かけなかった。

自分がググる限りではこのくらい(参考になってありがたかった)。

doudonn.com

であるから、1例を出しておこうというわけ。

諸条件は概ね以下の通り。

  • コンテナイメージはphp:8.4-fpmがベース
  • Laravel 11
  • vendor配下を含めての総phpファイル数は20000程度
  • app配下のphpファイル数は1500程度
  • resource配下のphpファイル数は1500程度
  • 日本語の文字列がバキバキにphpファイルにハードコードされまくっている

php.ini設定

OPcacheに関しては、 PHP: インストール手順 - Manual に「推奨される php.ini の設定」が示されているので、これを基本に考える。

opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1 ; PHP 7.2.0 より前のバージョンで有効
opcache.enable_cli=1

JITの設定の推奨も欲しいのだが、ざっと見た限りは見当たらなかった。

PHP: 実行時設定 - Manualに、多くの場合opcache.jitの設定はプリセットのtracingがいいだろうとあるので、それにしてopcache.jit_buffer_sizeを適当に割り振ってJITが動くようにする(デフォルト0指定で、0だと動かない。どのくらいの割り当てがいいかは書かれていない)。

しかしopcache.memory_consumptionは単位がMBなのに、opcache.jit_buffer_sizeはByteなのはどういうこっちゃ? 脳が混乱する。

運用状況を踏まえての調整

GitHub - amnuts/opcache-gui: A clean, effective and responsive interface for Zend OPcache で統計情報だけ眺めた程度。

opcache.memory_consumption=256
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=16229
opcache.revalidate_freq=60
opcache.enable_cli=1
opcache.jit = tracing
opcache.jit_buffer_size = 64M

↑な設定での運用状況をなんぼか抜粋した。

# ファイル
[num_cached_scripts] => 1476
[num_cached_keys] => 2923
[max_cached_keys] => 16229

# OPcacheメモリ
[total_memory] => 256.00MB
[used_memory] => 114.52MB
[free_memory] => 141.48MB

# OPcache文字列
[buffer_size] => 64.00MB
[strings_used_memory] => 21.38MB
[strings_free_memory] => 42.62MB
[number_of_strings] => 82,038

# JIT
[jit_buffer_size] => 64.00MB
[jit_buffer_free] => 63.07MB

memory_consumption, interned_strings_buffer, max_accelerated_filesは推奨から増やして、まぁこんなもんだろうと思う。max_accelerated_files は増やしすぎかもしれないが、Laravelのような巨大なフレームワークを使う場面では、全般に推奨設定からあふれる場面があるだろうと思う。

jit_buffer_size は、、、全然JIT動いてないんだろうか? 細かいJIT条件を精査するのは大変なので当面は忘れたい。

とはいえ、多分JIT割り当てのメモリはぬるぽっと減らすだろう。

いかがだったでしょうか? 多少の参考になれば幸いです。