それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

phpでバッチ処理は控えるべき?メモリ解放しないよ。

アマゾンの検索をするとき、PHPでバッチ処理を書いた。PHPで大量のリクエストを発行してAmazonECS結果を見ていた。ふとメモリ消費量を見る。ちびりそうになる。メモリ消費量が上昇し続ける。unset()をしているが、メモリの消費量は変化しない。



立ち止まって考える。当たり前じゃないか。PHPApacheのリクエスト毎に起動して、リクエスト終了時にメモリから全部消去される。バッチ処理が終わらないとメモリ解放されないのかね。処理が長くなれば不利じゃないか。繰り返し処理でメモリを再利用しない。なら、バッチの大量データを処理に不向きか。一応はコマンドラインで動きます程度なのね。


もし、PHPバッチ処理をするなら、バッチ処理の細切れな生成、消去を短時間に繰り返すしかないのね。

バッチ処理とは大量のデータを夜間などに処理する事。そう記憶している。他スクリプト言語も同じか。元もとメモリ管理が出来ないのだ。もし1時間以上かかるなら、1分のを60回起動するべきか。


ちなみに、PHP 5.1.2でテストしている。PHP 5.2.xからはメモリについて  --enable-malloc-mm が提供されている。memory_get_usage()を使って細かく調べられる。そのうち試してみたい。

追記

Apache/batchの比較
Apache
  1. PHPはリクエスト開始時にメモリを確保する。
  2. PHPはリクエスト終了後にメモリを消す
バッチしょり
  1. バッチ処理は起動時にメモリを確保する。
  2. バッチ処理は終了時にメモリを解放する。

と処理方法はほぼ同じだ。しかし

処理する量が大きく違う

  • バッチはリクエスト処理の1000倍分繰り返す。

と言うことがある。だからメモリはなかなか解放されず処理が遅くなる。

解決はこうする

  • バッチAは1回の処理をする。
  • バッチBはバッチAを1000回起動する。

サンプルコード

バッチA
<?php
$a = new Hoge("last");
$a->setAAA(true);
$a->save #重い処理
バッチB
<?php
 foreach( range(1,1000) as $a ) {
   sysmtem('php batchA'); #バッチAを起動する。
 }

こうすればメモリ消費量は小さくてスワップしないから速く終る。