こんにちは。開発のY.Mです。
PHPアプリケーションにおいて、メモリ関連のエラーのひとつに PHP Fatal error: Out of memory があります。
メモリ確保時に空きメモリが足りなかった場合に発生するエラーなのですが、空きメモリが充分にあっても発生する場合があります。
エラーが発生する条件
32bit版のPHPを使用していること。
7.x系、5.x系共に発生します。OSのアーキテクチャは関係なく、PHPのプロセスが32bitであることが条件です。
検証環境
Windows7 Professional SP1 32bit、及び64bit。他のOSについては未検証です。
検証のためPHP環境設定で memory_limit を -1 (無制限)や 2GB 以上の大きな値にしています。
エラーが発生するパターン その1
ひとつの変数に割り当てられているメモリサイズが大きくなると、空きメモリがいくらあってもメモリ確保に失敗して PHP Fatal error: Out of memory が発生します。
エラーが発生する割り当てメモリサイズは一定ではありませんが、およそひとつの変数に対してメモリが 200MB ~ 500MB 程度割り当てられると発生します。
ありがちなエラー発生パターンとして以下が挙げられます。
・肥大化したキャッシュやログファイルを file_get_contents 関数で読み込んだ。
・巨大な配列やオブジェクトを serialize した。
エラーが発生するパターン その2
PHPプロセスが使用している合計メモリサイズが 1.2GB ~ 1.7GB 程度になると PHP Fatal error: Out of memory が発生します。
エラーが発生する合計メモリサイズもパターンその1と同じく一定ではありません。確認した環境では5.x系より7.x系の方がより少ない合計メモリサイズでエラーが発生する傾向にありました。
32bit版PHPにおける合計メモリサイズの上限は1GB程度までと考えるのが良さそうです。
原因
おそらく、32bitプロセスにおける使用可能メモリの制限に引っかかっているようです。
64bit版PHPの場合は同条件でもエラーは発生せず、memory_limit までメモリを使い切れました(空きメモリ > memory_limit の場合)。
解決方法
(1) 64bit版のPHPを使用する
64bit版のPHPであればエラーは発生しませんので、64bit版のPHPへ移行する事で解決できます。
しかしながら、ミドルウェアの更新やアプリケーション全体の動作検証が必要となるため、現実的に考えると簡単な事ではないでしょう。
これから新規にPHPアプリケーションの開発をするのであれば、最初から64bit版で開発することをお勧めします。
(2) コードを修正してメモリ使用量を削減する
どうしても32bit版のPHPを使うしかない場合、コードを修正してメモリの使用量を削減する他ありません。
今 PHP Fatal error: Out of memory が発生していなくても、扱うデータ量が増えたりする事で将来的に発生するおそれがあります。
file_get_contents 関数や serialize 関数の使用など、ひとつの変数に多くのメモリを割り当ててしまうおそれがある処理がないか、扱っているデータが巨大化した時にメモリ使用量が増大しないか確認し、エラーの原因となりうるコードがあれば早めに対処しておきましょう。
まとめ
メモリ関連のエラーはある日突然発生し、対処に苦慮する事が少なくありません。
アプリケーションの規模が大きくなってからエラーが発生すると対処が困難になりますので、日頃からメモリ使用量に気を付けてコーディングするよう心がけておきましょう。