Neden PHP Doctine ücretsiz () çalışmıyor?

6 Cevap php

Bu bir orada sizin herhangi Doktrini kullanıcıları için olduğunu. Ben işleme olmamıştır girişlerini bulmak için her n saniye bir tablosunu denetler bir PHP CLI cini süreç var. Bu temelde bir FIFO bulunuyor. Her neyse, ben hep öğreti kaynaklarını boşaltmak değil becuase PHP için ayrılan belleğini aşabilir. Bu sorunla mücadele etmek için bu sorgu nesnesi için ücretsiz sağlamaktadır. Ben olsa iş yapmak için görünmüyor olabilir. İşte kod:

 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();

Ben ne yapıyorum yanlış Herhangi bir fikir?

EDIT: Ben 1.0.3 kullanıyorum

EDIT: Ben aşağıda önerilerin hepsini denedim. Ben çok unset() buldum önce orada vardı gibi umutlu free() idi.

Burada muhtemelen herhangi bir yardım yardımcı olmak için daha fazla kod olduğunu. Eğer bağlantı açılış ve kapanış soru önce çocukları çoğaltılır ve gelen ben bağlantı benzersiz olmak zorundadır yaşamış cini süreç olacaktır.

  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

Bazı örnek çıktı:

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

6 Cevap

Sorun free() bellekten Doktrini nesneleri kaldırmak olmadığını, ama sadece mümkün temizleme çöp toplayıcı bu nesneler için yapım, bu nesneler üzerinde dairesel referanslar ortadan kaldırır. 23.6 Free Objects in bakınız Doctrine manual,

As of version 5.2.5, PHP is not able to garbage collect object graphs that have circular references, e.g. Parent has a reference to Child which has a reference to Parent. Since many doctrine model objects have such relations, PHP will not free their memory even when the objects go out of scope.

For most PHP applications, this problem is of little consequence, since PHP scripts tend to be short-lived. Longer-lived scripts, e.g. bulk data importers and exporters, can run out of memory unless you manually break the circular reference chains. Doctrine provides a free() function on Doctrine_Record, Doctrine_Collection, and Doctrine_Query which eliminates the circular references on those objects, freeing them up for garbage collection.

Çözelti, kullandıktan sonra unset() $query nesneye olmak free() olmalıdır:

$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 ayrıca sadece Doctrine_Collection üzerinde () ücretsiz aradığınız anda, ücretsiz () yöntemi vardır, örneğin, deneyin:

 $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();

Doktrini (sadece bazı faiz Bunu bu hafta sonu keşfettiği gibi ...), öylesine almak ya da benim tahminim terk ile hiçbir deneyimi ... ^ _ ^

Ben denemek ve çalıştırmak kısmından sorgu oluşturulması ayırmak olacaktır:

$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();

Emin değil ne döner yürütmek, ama sadece durumda, birileri bir daha aydın tavsiyesi olmadığı sürece ... denemeye değer! :-P

$ Sorgu-> Ücretsiz (true) deneyin;

(?)

Ben sadece o kadar sorgu yok, çünkü gerçekten her ORM gerekmez arka-uç parçaları için PDO kullanmak için gidiyoruz düşünüyorum. Ben sadece gerçekten bu sistemdeki tüm uygulamalar arasında DB ile etkileşim için bir tek yol var istedim. Belki biraz daha fazla düşünce vereceğim.

Bu eski bir yazı olduğunu, ve muhtemelen Doktrin 1.x çok daha fazla kullanılmaz, ama ben yine de burada bağlantı: php/symfony/doctrine memory leak?

Orada teknikleri deneyebilirsiniz.