2008-11-17 23 views
5

这是一个适用于你的任何一个学说用户。我有一个PHP CLI守护进程,每隔n秒检查一次表以查找尚未处理的条目。它基本上是一个FIFO。无论如何,我总是超过分配给PHP的内存,因为主干没有释放它的资源。为了解决这个问题,它为查询对象免费提供。我似乎无法让它工作。下面的代码:为什么PHP Doctine的free()不能正常工作?

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 

回答

4

的问题是,free()不会删除从存储器学说对象,但只是消除了对这些对象的循环引用,从而有可能为垃圾收集器清理那些对象。请参阅23.6 Free ObjectsDoctrine manual

随着5.2.5版本中,PHP是不是能 垃圾收集的对象图是 有循环引用,例如父 有一个引用Parent的引用 。由于很多 原则模型对象具有这种关系,即使对象超出 范围,PHP也不会释放其内存 内存。

对于大多数PHP应用程序,这 问题是无关紧要的,因为 PHP脚本往往是 昙花一现。更长寿的脚本,例如 批量数据导入程序和 导出程序可能会耗尽内存 ,除非您手动打破参考链的圆周 。学说提供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 
+0

我真的很希望那个。我甚至在发现有关免费之前就已经解决了,于是我匆匆删除了它。即使它回来,它不工作。 – 2008-11-17 20:31:31

0

没有与学说(只是一些利益,我发现它这个周末......)的经验,所以采取或离开我的猜测...^_^

我会尝试,并从其执行分出一部分建立查询:

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

不知道该怎么执行的回报,但以防万一,值得一试......除非有人有更开明的建议! :-P

+0

我是一个完整的n00b自己。我有同样的想法,但没有任何不同。 – 2008-11-17 15:59:42

0

Try $ query-> free(true);

(?)

+0

对不起,我应该概述一下我实际已经尝试过的东西。尽管这是我的第一次,但无济于事。 – 2008-11-17 16:12:49

0

我想我可能只是要使用PDO的后端部分真的不需要ORM反正因为没有那么多的查询。我真的很想在这个系统中的所有应用程序中使用单一的方式与数据库进行交互。也许我会再考虑一下。

1

Doctrine_Query还设有免费的()方法,此刻你只是在你的Doctrine_Collection,如调用free(),尝试:

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