Вопрос

Это один из вариантов для любого из вас, пользователей Doctrine.У меня есть процесс демона PHP CLI, который проверяет таблицу каждые n секунд, чтобы найти записи, которые не были обработаны.По сути, это ФИФО.В любом случае, я всегда превышаю объем памяти, выделенный PHP, потому что Doctrine не освобождает свои ресурсы.Для решения этой проблемы он предоставляет бесплатный объект запроса.Кажется, я не могу заставить это работать.Вот код:

 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

РЕДАКТИРОВАТЬ:Я попробовал все приведенные ниже предложения.Я очень надеялся на unset() как оно было у меня там до того, как я нашел free().

Вот еще код, который может помочь в любой помощи.Прежде чем вы зададите вопрос об открытии и закрытии соединения, это будет демонический процесс, который порождает детей, и, насколько я знаю, соединение должно быть уникальным.

  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 бесплатных объектов в разделе Руководство по доктрине :

  

Начиная с версии 5.2.5, PHP не может   мусора собирать графы объектов, которые   иметь круговые ссылки, например родитель   имеет ссылку на ребенка, который имеет   ссылка на Родителя. Поскольку многие   Объекты модели доктрины имеют такие   отношения, PHP не освободит их   память, даже когда объекты выходят из   сфера.      

Для большинства приложений PHP это   проблема не имеет большого значения,   поскольку PHP-скрипты, как правило,   кратковременный. Долгоживущие сценарии,   например импортеры больших объемов данных и   экспортеры могут исчерпать память   если вы не разорвете вручную   цепочки ссылок. Доктрина обеспечивает   функция free () для Doctrine_Record,   Doctrine_Collection, и   Doctrine_Query, который устраняет   циркулярные ссылки на эти объекты,   освобождая их от мусора   коллекция.

Решением должно быть unset () объект $ query после использования free () :

$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 (), в данный момент вы просто вызываете free () для вашей коллекции Doctrine_Collection, например, 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->free(true);

(?)

Я думаю, что я мог бы просто использовать PDO для внутренних частей, которые действительно не нуждаются в ORM, так как запросов не так много. Я просто очень хотел иметь единый способ взаимодействия с БД во всех моих приложениях в этой системе. Может быть, я еще немного подумаю.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top