2008-11-17 26 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();