質問

これは、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とやり取りするための単一の方法が本当に必要でした。もう少し考えてみたいと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top