PHP Doctineのfree()が機能しないのはなぜですか?
質問
これは、Doctrineのユーザーを対象としています。 n秒ごとにテーブルをチェックして、処理されていないエントリを見つけるPHP CLIデーモンプロセスがあります。基本的にはFIFOです。とにかく、Doctrineはリソースを解放しないため、PHPに割り当てられたメモリを常に超えます。この問題に対処するために、クエリオブジェクトに無料で提供します。私はそれを動作させることができないようです。コードは次のとおりです。
22 print "You are using " . (memory_get_usage() / 1024). "\n";
23 $query = Doctrine_Query::create()
24 ->from('SubmissionQueue s')
25 ->where('s.time_acted_on IS NULL')
26 ->orderby('s.time_queued')
27 ->limit(1)
28 ->execute();
29 print $query[0]->time_queued . "\n";
30 $query->free();
私が間違っていることは何ですか?
編集:1.0.3を使用しています
編集:以下の提案をすべて試しました。 free()
を発見する前に unset()
があったので、私は非常に期待していました。
ヘルプに役立つ可能性のあるコードを次に示します。接続の開始と終了を疑問視する前に、子プロセスを生成するのはデーモンプロセスであり、私が経験した接続は一意でなければなりません。
1 <?php
2
3 require_once('/usr/local/lib/php/Doctrine/lib/Doctrine.php');
4
5 spl_autoload_register(array('Doctrine', 'autoload'));
6
7 $manager = Doctrine_Manager::getInstance();
8 $manager->setAttribute('model_loading','conservative');
9 Doctrine::loadModels('lib/model/master');
10
11 while(1){
12 print "You are using " . intval(memory_get_usage() / 1024) . "\n";
13 $manager->connection('********************************************','master');
14 $query = Doctrine_Query::create()
15 ->from('SubmissionQueue s')
16 ->where('s.time_acted_on IS NULL')
17 ->orderby('s.time_queued')
18 ->limit(1)
19 ->execute();
20 print "[" . $query[0]->time_queued . "]\n";
21 $query->free();
22 unset($query);
23 $query = null;
24 $manager->closeConnection(Doctrine_Manager::getInstance()->getConnection('master'));
25 sleep(5);
26 }
27
サンプル出力:
You are using 14949KB
[2008-11-17 13:59:00]
You are using 14978KB
[2008-11-17 13:59:00]
You are using 15007KB
[2008-11-17 13:59:00]
You are using 15035KB
[2008-11-17 13:59:00]
You are using 15064KB
[2008-11-17 13:59:00]
You are using 15093KB
[2008-11-17 13:59:00]
You are using 15121KB
[2008-11-17 13:59:00]
You are using 15150KB
[2008-11-17 13:59:00]
You are using 15179KB
[2008-11-17 13:59:00]
You are using 15207KB
[2008-11-17 13:59:00]
You are using 15236KB
[2008-11-17 13:59:00]
You are using 15265KB
[2008-11-17 13:59:00]
You are using 15293KB
[2008-11-17 13:59:00]
You are using 15322KB
解決
問題は、 free()
はメモリからDoctrineオブジェクトを削除せず、それらのオブジェクトの循環参照を削除するだけで、ガベージコレクターがそれらのオブジェクトをクリーンアップできるようにすることです。 23.6 Free Objects をご覧ください。 Doctrineマニュアル:
バージョン5.2.5の時点では、PHPは オブジェクトグラフをガベージコレクションする 循環参照があります。親 を持つChildへの参照があります。 親への参照。多くの ドクトリンモデルオブジェクトには 関係、PHPはそれらを解放しません オブジェクトが出てもメモリ スコープ。
ほとんどのPHPアプリケーションでは、これ 問題はほとんど重要ではありません、 PHPスクリプトは 短命。寿命の長いスクリプト、 例えばバルクデータインポーター エクスポーター、メモリが不足する可能性があります 手動で円形を壊さない限り 参照チェーン。 Doctrineは Doctrine_Recordのfree()関数、 Doctrine_Collection、および を排除するDoctrine_Query それらのオブジェクトの循環参照、 ゴミのために解放する コレクション。
解決策は、 free()
を使用した後に $ query
オブジェクトを unset()
することです。
$query = Doctrine_Query::create()
->from('SubmissionQueue s')
->where('s.time_acted_on IS NULL')
->orderby('s.time_queued')
->limit(1);
$query->execute();
print $query[0]->time_queued . "\n";
$query->free();
unset($query); // perhaps $query = null; will also work
他のヒント
Doctrine_Queryにはfree()メソッドもあります。現時点では、Doctrine_Collectionでfree()を呼び出しているだけです。例:try:
$query = Doctrine_Query::create()
->from('SubmissionQueue s')
->where('s.time_acted_on IS NULL')
->orderby('s.time_queued')
->limit(1);
$results = $query->execute();
print $results[0]->time_queued . "\n";
$results->free();
$query->free();
Doctrineの経験がありません(今週の終わりに気付いたのはちょっと興味があります...)。
クエリの作成と実行部分を分けてみます:
$query = Doctrine_Query::create()
->from('SubmissionQueue s')
->where('s.time_acted_on IS NULL')
->orderby('s.time_queued')
->limit(1);
$query->execute();
print $query[0]->time_queued . "\n";
$query->free();
executeが何を返すかはわかりませんが、念のため、試してみる価値はあります。 :-P
$ query-&gt; free(true);を試してください
(?)
クエリがあまり多くないので、とにかくORMを本当に必要としないバックエンド部分にPDOを使用するだけだと思います。このシステムのすべてのアプリでDBとやり取りするための単一の方法が本当に必要でした。もう少し考えてみたいと思います。