为什么PHP Doctine的free()不起作用?

Chr*_*anz 5 php memory orm doctrine

这是一个适用于你们任何一个Doctrine用户的人.我有一个PHP CLI守护进程,每隔n秒检查一次表,以查找尚未处理的条目.它基本上是一个FIFO.无论如何,我总是超过分配给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();
Run Code Online (Sandbox Code Playgroud)

我有什么想法我做错了吗?

编辑:我使用的是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
Run Code Online (Sandbox Code Playgroud)

一些示例输出:

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
Run Code Online (Sandbox Code Playgroud)

Ste*_*rig 6

问题是,这free()不会从内存中删除Doctrine对象,只是消除了对这些对象的循环引用,使垃圾收集器可以清理这些对象.请参阅Doctrine手册中的23.6 Free Objects:

从版本5.2.5开始,PHP无法垃圾收集具有循环引用的对象图,例如,Parent具有对Child的引用,该引用具有对Parent的引用.由于许多学说模型对象具有这样的关系,即使对象超出范围,PHP也不会释放它们的内存.

对于大多数PHP应用程序来说,这个问题并不重要,因为PHP脚本往往是短暂的.除非您手动断开循环引用链,否则寿命较长的脚本(例如批量数据导入程序和导出程序)可能会耗尽内存.Doctrine在Doctrine_Record,Doctrine_Collection和Doctrine_Query上提供了一个free()函数,它消除了对这些对象的循环引用,将它们释放出来进行垃圾回收.

该解决方案应该是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
Run Code Online (Sandbox Code Playgroud)