PHPはリファレンスカウントGCを使っているというお話
バイト先でHyper Estraierを使った全文検索機能を実装する機会がありました。
そこで、EstraierPureライブラリを使って、PHPスクリプトを通じてHyper Estraierにテキストのインデックスを作成させるようにしたのですが、複数のテキストファイルをインデックス化する途中で下記PHPエラーが出てPHPプロセスが終了しました。
PHP Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 22423 bytes) in /var/lib/Services/HyperEstraier/Utility.php on line 278
なんかメモリが足りなくなっとるらしい。
また、インデックス化に失敗したテキストファイルから実行再開すると、そのテキストのインデックス化に成功した後、別のテキストファイルをインデックス化する時に同様のエラーが出てプロセスが終了します。
以上の結果からメモリリークの疑いが強いのですが、EstraierPureは100%PHPコードなので、PHPのメモリ管理に原因がありそうです。
ということで、PHPのメモリ管理方法を調べてみたところ、リファレンスカウント方式のGCだと判明しました*1。今までTracing GC系だと思ってたよ・・・
現在、PHPのリファレンスカウントGCは循環参照しているオブジェクトは解放できません。おそらく、EstraierPureの中で循環参照があって、そのオブジェクトが解放されずにリークし、最終的にメモリが足りなくなるのでしょう。
PHP6からは、Pythonでも使われているCycle Collector*2が実装されるそうなので*3、今回の問題もPHP6を使えば解消します。
ってまだPHP6は正式リリースされてないし、今更PHP5から変えられるかーっていう状況。PHP5.3でもCycle Collectorが導入されるといいなあ。・・・結局リリース待ちなわけだけど。
*1:PHPカンファレンス2007 「PHPの今とこれから 2007」:http://www.php.gr.jp/seminar/20070901/data/phpcon070901a.ppt
*2:Cycle Collectorアルゴリズムの論文: http://www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf
*3:PHPカンファレンス2007 「PHPの今とこれから 2007」:http://www.php.gr.jp/seminar/20070901/data/phpcon070901a.ppt