TECHBLOGスキルブログ

PHP7.4で導入されるPreload(プリロード)って何?

2019.09.27

こんにちは。
ユニトラストの宮本です。

最近、PHPの実行スピードが改善されており、普段PHPを使っている私としてはとても嬉しく思っています。

2019年の末頃にリリースされる予定のPHP7.4の新機能に「Preload」という機能があります。
一体どういう機能なんでしょう?

preloadってどんな機能?

PHPは実行時にロード(読み込み)・パース(構文解析)・コンパイル(実行命令への変換)されて動作しています。
実行時に毎回ロード・パース・コンパイルしていてはどうしてもスピードが遅くなってしまいます。

その為、PHP5.5以降ではOPcacheという機能が標準搭載されています。
OPcacheは一度実行されたPHPファイルをメモリ上にキャッシュすることで実行時に毎回ロード・パース・コンパイルすることなく実行させ高速に動作させる機能です。
ただ、初回の実行はPHPファイルのロード・パース・コンパイルがおこなわれるので、スピードが改善されない問題がありました。

PHP7.4から導入されるPreloadではサーバ起動時にあらかじめ設定したPHPファイルを事前にロード・パース・コンパイルし、メモリ上にキャッシュさせることで確実に動作を高速化させることができます。

preloadの使い方

PHPの設定ファイル(php.ini)にopcache.preloadという項目が追加されています。
まず、この項目にPHPファイルを指定します。

opcache.preload="hoge/huga/preload.php" 

指定したPHPファイル内で事前にキャッシュさせるPHPファイルを指定します。

opcache_compile_file('apppath/hogehoge.php');
opcache_compile_file('apppath/hugahuga.php');

上記のようにopcache_compile_file関数にPHPファイルを指定することで、サーバ起動時にキャッシュをおこないます。

preloadを使うとどうなる?

PHP RFC: Preloadingを読んでみましょう。
サンプルとして、Zend Framework全体をプリロードするスクリプトが書かれています。

<?php
function _preload($preload, string $pattern = "/\.php$/", array $ignore = []) {
  if (is_array($preload)) {
    foreach ($preload as $path) {
      _preload($path, $pattern, $ignore);
    }
  } else if (is_string($preload)) {
    $path = $preload;
    if (!in_array($path, $ignore)) {
      if (is_dir($path)) {
        if ($dh = opendir($path)) {
          while (($file = readdir($dh)) !== false) {
            if ($file !== "." && $file !== "..") {
              _preload($path . "/" . $file, $pattern, $ignore);
            }
          }
          closedir($dh);
        }
      } else if (is_file($path) && preg_match($pattern, $path)) {
        if (!opcache_compile_file($path)) {
          trigger_error("Preloading Failed", E_USER_ERROR);
        }
      }
    }
  }
}
 
set_include_path(get_include_path() . PATH_SEPARATOR . realpath("/var/www/ZendFramework/library"));
_preload(["/var/www/ZendFramework/library"]);

性能に関する部分を読む限り、

Using preloading without any code modification I got ~30% speed-up on ZF1_HelloWorld (3620 req/sec vs 2650 req/sec) and ~50% on ZF2Test (1300 req/sec vs 670 req/sec) reference applications. However, real world gains will depend on the ratio between the bootstrap overhead of the code and the runtime of the code, and will likely be lower. This will likely provide the most noticeable gains with requests with short very runtimes, such as microservices.

zend frameworkで最大50%前後の性能アップが見込めるようです。(実際の利用シーンではもっと低くなるとも書かれています。)
また、マイクロサービスで構築する際により性能アップを実感できそうと書かれています。

preloadの難しいトコロ

一見良いことづくしに思えますがPHP RFC: Preloadingに以下の記述があります。

As mentioned above, preloaded files remain cached in opcache memory forever. Modification of their corresponding source files won’t have any effect without another server restart. All functions and most classes defined in these files will be permanently loaded into PHP’s function and class tables and become permanently available in the context of any future request. During preloading, PHP also resolves class dependencies and links with parent, interfaces and traits. It also removes unnecessary includes and performs some other optimizations.

opcache_reset() is not going to reload preloaded files. It’s just not possible using current opcache design, because during restart, they may be used by some process, and any modifications may lead to crash.

プリロードされたPHPファイルはサーバ起動時にロード・パース・コンパイルされ、メモリに展開された状態になり、PHPファイルを編集しても変更が反映できません。
また、OPcacheをクリアするopcache_reset関数を使用しても、プリロードされメモリに展開されたPHPファイルのキャッシュはリセットされません。

現状、変更を反映する方法はサーバの再起動しかありません。
何を再起動しなければいけないかはサーバの構成により変わるので、構成に合わせて判断しましょう。

その他、preloadするときのPHPファイルの記述方法に制限があるので、試す前にPHP RFC: Preloadingを読んで見ることをお勧めします。

まとめ

今回はPHP7.4の新機能preloadについて簡単に解説しました。
技術の進化は日進月歩です。
新しいものは常にチェックして、快適なサービスを届けられるようにしていきたいですね。

ちなみに、PHPの次期バージョン(PHP8)ではコンパイル言語に匹敵する速度が出せるようになる仕組み(JustInTimeコンパイラ)が導入される予定になっています。
期待して、リリースを待ちましょう!私も楽しみにしています!

ユニトラストでは、一緒に働けるメンバーを募集しています!詳しくは↓バナーからどうぞ!


              

OTHER CONTENTSその他のコンテンツ

UNITRUST会社を知る

  • 私たちについて

  • 企業情報

SERVICE事業内容

  • システム開発

CONTACT
お問い合わせ

あなたの「想い」に挑戦します。

どうぞお気軽にお問い合わせください。

受付時間:平日9:00〜18:00 日・祝日・弊社指定休業日は除く

お問い合わせ