概要
phpで負荷の高いプログラムを書いてるときに
Allowed memory size of ~~ みたいなメモリ不足エラーがでることがままあるが、
普段このエラーが発生したときは脳みそ停止して、
「php.iniのmemory_limit調整しなきゃ・・・」みたいに思ってたんだけど、
そもそもプログラム側にメモリの無駄があるんじゃないかと思い色々調べた話です。
不要になった変数の解放
普段あまり意識してなかったけど、
当然と言えば当然だが、プログラム上で変数に値を持たせれば
その容量に応じてメモリを使ってることになる。
PHPにはガベージコレクションという仕組みがあって、
関数とかのまとまった処理を抜けると、そこで使っていた変数は勝手に開放されるらしい
(この辺はまだちゃんと調べてないが・・・)
言い換えれば、関数とかを抜けなかったらメモリは勝手に開放されないわけで・・・
例えば、
DBからデータを抽出→インポート用にデータを変換→他DBにデータをインポート
みたいな処理を考える
# データの抽出
$export_data = $this->dataExport();
→ ここで大量のデータをエクスポート
# データの変換
$import_data = $this->dataTransform($export_data);
→ エクスポートしたデータをインポート用に変換
# データのインポート
$this->dataImport($import_data);
→ ...メモリエラー発生
上記のようなプログラムでは、
抽出するデータ量が膨大だと、それだけのデータを$export_dataに格納し続けることになるので、
その分だけメモリを抱え込むことになる。
それが原因で、後続処理でメモリエラーが発生するかもしれない
データ変換後であれば、抽出データは必要ないはずなので、
データ変換後に、$export_dataを明示的に開放してやると、メモリエラーを回避できるかもしれない。
# データの抽出
$export_data = $this->dataExport();
→ ここで大量のデータをエクスポート
# データの変換
$import_data = $this->dataTransform($export_data);
→ エクスポートしたデータをインポート用に変換
# export_dataの開放
unset($export_data);
# データのインポート
$this->dataImport($import_data);
→ ...メモリエラーなく実行できる、かも?
自分が作っていたプログラムだと、これでメモリエラーが回避できたので
なるほどなぁって感じでした。
プログラムの最適化も大切という話
メモリ不足となって、php.iniの値を512M,1024M,2048M...と大きくするのも一つだけど、
まずはプログラムに無駄なコードが無いかを見直してみるのが大切かもしれないですね。
もちろん、それでもメモリ不足なるならiniをいじってやらないといけないかもしれませんけども。