PHPのメモリについて(Part1)

f:id:yukitakai:20200805180100j:plain

どうもこんにちは。BriswellのTuanと申します。 一年半前に日本へ来ました。日本語はまだ下手ですが、今回自社の活動協力の為、少しPHPの知識共有したいと思います。 PHPは入社後に始めたので経験は少ないですが、間違いがありましたらコメントで教えていただけると助かります。

PHPは自動的にメモリ管理できますので、初めてPHP使った開発者はメモリ管理を気にしなくてもいいと考えるかもしれません。 しかし、実際のプロジェクトでは「Fatal error: Out of memory」エラーを目にしたことがあると思います。

なぜでしょうか? PHPの問題でしょうか?自分達の実装に問題があるのでしょうか?

以上の質問の為今回PHPのメモリの重要性について記載します。

①はじめに、PHPのメモリ上限は?どこで設定するのか? 環境(OS)によってPHPの設定ファイル置場は異なりますが、ファイル名は同じ「php.ini」です その設定ファイルに「memory_limit」と言う設定項目があり、そこでメモリ上限が分かります。

  例えば:

memory_limit  = 128MB (デフォルト)

調整できる?

できます。ただし、物理のメモリの上限を注意してください。

PHPは他のコンパイラインタプリタツールと同じく、メモリが必要です。
すべての変数がメモリを消費します。
変数のメモリは、使用されなくなったときに解放されます。
解析スクリプトにはメモリが必要です。
リクエストが終了すると、スクリプトを解析するためのメモリが解放されます
これは重要か?
大切です。ローカル変数だと、関数の実行が終わったら解放されますが、
グローバル変数だとスクリプトまたはアプリが終了後に解放されますので、そこまでメモリを保持します。

③Includeスクリプトの解析には、クラスよりメモリを消費します。
例えば簡単のスクリプト確認しましょう:
Includeパタン

  hello.php

<?php               
echo "Hello world!\n";              

  example.php

<?php               
$mem = memory_get_usage();              
require "hello.php";                
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";                

  実行の結果は下記の通りです。
  php example.php

Hello world!                
>> used mem: 152    

クラスパタン

  example1.php

<?php   
$mem = memory_get_usage();  
class HelloClass {  
    public function sayHi() {   
                echo "Hello World\n";   
    }   
}   

$obj = new HelloClass();    
$obj->sayHi();  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";    

  実行の結果は下記の通りです。
  php example1.php

Hello world!    
used mem: 72

メモリ容量はByteです。結果を見ると、クラスの実装はちょっと面倒ですけど効率的です。 Includeはクラスの実装よりメモリを2倍使用しました。 MVCプロジェクトにViewの場合はIncludeを使用してもいいですが、Controllerなどはクラスの方を使用してください。

④オーバーヘッドメモリ
例えば下記のスクリプト

  example2.php

<?php
$mem = memory_get_usage(); 
$a = str_repeat('a', 1024); 
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";

  実行の結果は下記の通りです。
  php example2.php

>> used mem: 1280

なぜでしょうか?基本的に$aは1024桁数、1桁数1Byteですが、結果は1280Byteになります。

原因としてはPHPのメモリ管理方はオーバーヘッドあるためです。

細かいことは次回話しましょう。

オーバーヘッドがありますので、PHPのメモリは上限設定ギリギリまで使わないでください。