メモリー枯渇
会社では見積書をExcelで1枚1枚作成し、過去の分をそのまま保存して1通1ファイルで残している。しかも、何かの基準でフォルダを分けたりしていない。結果、そのフォルダのファイル数は64,000を超えてしまった。台帳(Excel)管理していて、台帳ではファイルにリンクまではってて、おいそれと場所を移動できない・・・そう、32ビット版のExcelは今でも65,535行が最大行数。破たんするまでカウントダウンしている状態「なら台帳をデータベース化してしまって、ついでに保存場所もフォルダ階層を管理してしまおう」と思った。やるなら、フォルダの整理をして、その結果をデータベースに記録したい。手間なんてかけたくないから自動で・・・・Perl・・・・・・・・・昔使ったけど、忘れちまって思い出せないWindowsPowerShell ・・VBなら書いたことくらいあるが、.net覚えないと便利に使えなさそう。PHP ・・・・・・・・・一応かける。そして何も考えずにPHPでCLI用のサンプルコード書いてみた。内容は・ディレクトリのファイル一覧取得・1行づつ処理して、PHPexcelでオープン・特定セルの値を取得して、とりあえず標準出力みたいな感じそしたら、ファイルリストを何行か処理しただけで、コケやがんの。「Allowed memory size of xxxxxxxxx bytes exhausted」だって。大きなファイル開いて失敗したのかと思って、php.iniのmemory_limitの値を広げてみたそうすると、チョットだけ進んで・・・・でも同じ結果。「え?コードの書き方悪くてメモリーリークしてる??」なんて思ったが、オブジェクトをクローズしようが、nullを入れてみようが、結果が変わらない。PHPexcelのメモリーリークとか調べてみたけど、自分の環境で起きてるようなのとは事例が違う。ちょっと挫折したよ。調べてるうちに、「SAPIのPHPはリクエストの処理が完了するまでメモリーを開放しない」「つまりCLIはバッチ処理が完了するまでメモリーを開放しない」的な内容を書いてるブログを発見。「PHP バッチ処理 メモリ解放」あたりで検索すると、見つかったり見つからなかったり・・・で、そっち系統で調べてみると、PHPでバッチ処理するときは、にメモリを消費するスクリプトを分けて(hogehoge1.php、hogehoge2.phpのよう)コーディングして、それらを実行する親のPHPスクリプトを、次のように用意する。<?PHP // 投稿用に全角にしていますsystem("php hogehoge1.php");system("php hogehoge2.php");?>等と書くと、メインのPHPコードは終了しないが、個別のほうは短い単位で終了するためメモリー消費が少なくて済むとか。実行に使用する関数をexec(),shell_exec(),passthru(),system(),pcntl_exec()のどれを使うかは、用途に応じてきちんと使い分ける必要がある。(結果の戻し方や、標準出力の出力先に差がある)探せば、こんな感じの記事が何件か見つかるんだけど、たどり着くまで時間がかかったので、自分もログとして残してみる。誰かの苦労が、こんなことで半減できればいいな。