Endnote XML参考文献ファイルからレコードをデータベースにインポートするPHPプラグインを作成しました。インポート プロセスにはいくつかの段階が含まれます。そのうちの 1 つは、Endnote レコードをメモリに最初に読み込み、内部のオブジェクト ベースの表現を作成することです。次に、インポートするすべてのレコードをスキャンして、著者、出版物、キーワードなどに対応するレコードがデータベースに既に存在するかどうかを確認する必要があります。
OS X 10.8.2 で PHP 5.4.7 (64 ビット) を実行しています。
これらのタスクを迅速に達成するために、データベースにデータを書き込んだり、データベースを繰り返し参照したりするのではなく、ほぼすべてのデータをメモリに保存しています...必要なデータはすべて一度に読み込まれ、必要に応じて参照されます。
もちろん、これはメモリ集約的です。ただし、メモリ使用量を減らすのに非常に効果的なメモリ フットプリントを減らすための戦略をいくつか開発しました。特に、ネイティブ PHP シリアライゼーション/アンシリアライゼーション機能を zlib と併用して、シリアライズされた表現を圧縮します。それでも、メモリ使用量は依然として不快なほど高く、500 の Endnote レコードをインポートしただけで最大メモリが使い果たされます。
これを解決するために、unset()
内部関数を使用して、不要になったすべての変数、配列、およびオブジェクトの割り当てを解除しようとしました。これらのオブジェクトの一部は、インスタンス化すると非常に大きくなるため、できるだけ早く破棄します。ただし、いくつかのメモリ使用量のプロファイリングを行った後、 で報告されたメモリ使用量が減少memory_get_usage(true)
していないことがunset
わかりました。gc_enable()
gc_collect_cycles()
特定の変数の参照カウントがゼロにならない限り、PHP は関連するメモリを解放しないことを示す他の投稿を読みましたが、これは理解しています。循環参照を回避するようにコードを設計しました...メモリを消費する個別のオブジェクトのそれぞれには、独立した内部ストレージ配列のセットがあり、他のオブジェクトとデータを共有するものはありません。したがって、理論的には、ホスト オブジェクトを破棄すると、そのすべてのプライベート データがすぐに解放されます。しかし、私はこれが起こっているのを見ていません。
誰かが私のコードを見たい場合は、Githubで入手できます。
1.さまざまなメモリ使用量の高いオブジェクトをペースでテストし、メモリ使用量を測定する本体テスト (500 Endnote レコードを処理し、合計 122MB を使用) がファイル内にあります。/test/ObjectStoreTest.php
2. Endnote データを解析し、それをオブジェクトベースの表現に変換するためのルーチン (実行中に約 15MB を使用) は、次の場所にあります。/controller/ParseAndStoreEndnoteRecordsHandler.class.php
3.メイン データベースの既存の著者を発見するためのクラス (約 30MB を使用するようです) は、次の場所にあります。/model/resolvers/CreatorExternalReferenceResolver.class.php
質問に答えるために必要な場合に備えて、この情報を参照用に提供します...明らかに、私のコードの分析に半日を費やす人はいないと思います。ただし、この情報で、私が抱えている特定のメモリ使用量の問題を明確に特定できることを願っています。