2011-10-05 77 views
6

我有一個php腳本,它使用Doctrine2和Zend來計算數據庫中的一些內容,併爲30.000個用戶發送一些電子郵件。有沒有辦法知道我在記憶中擁有哪些對象和多少個對象?

我的腳本正在泄漏內存,我想知道哪些是消耗內存的對象,以及是否有可能誰保留對它們的引用(因此不允許它們被釋放)。

即時通訊使用PHP 5.3.x,所以普通的循環引用不應該是問題。

我試過使用xdebug跟蹤功能來獲取mem_delta沒有成功(太多的數據)。

我試着在重要功能之前和之後手動添加memory_get_usage。但我得到的唯一結論是,每個用戶約有40萬個用戶,而用戶數量達到3000個,這給我提供了我可用的1Gb。

是否有其他方法可以知道內存泄漏的位置和原因? 感謝

+1

那麼,用戶應該一個接一個的處理,應該只有400k的內存需要!如果每個週期都增加內存使用量,那麼設計中的某些內容就會嚴重錯誤! – markus

+0

那麼,我有一個循環,調用一個函數,執行以下操作:獲取用戶的信息,計算(包括存儲),發送郵件,釋放資源。並且每個用戶都是相互獨立的,所以資源不會被釋放 –

+0

你看過教條的實體管理者嗎?我對教義不是很熟悉,但它可能會存儲對所有30k用戶的實體/代理/ ...的引用。 – Fge

回答

2

你不妨試試說10封電子郵件,然後將這個

get_defined_vars(); 

http://nz.php.net/manual/en/function.get-defined-vars.php

在腳本結束時或發送電子郵件後(取決於你的代碼是如何設置) 。

這應該告訴你什麼仍然加載,以及你可以取消設置/變成參考。

另外,如果有兩件很多事情加載,你可以在代碼的開始和結尾附近找到差異。

+0

謝謝,這似乎很有幫助。我會在我的循環中嘗試。從文檔中,唯一讓我擔心的是它只給我關於範圍內的對象的信息。我猜測內存問題因爲超出範圍而退出。 –

0

這不是一個工具,它會給你你需要的東西,但它可能會幫助你。如果你還沒有,你可以實現身份地圖模式,每次你創建一個對象時,它都會使用身份地圖進行註冊,所以你可以在任何時候調用IM並查看加載了哪些對象或者告訴它卸載任何對象加載對象。

http://martinfowler.com/eaaCatalog/identityMap.html

+0

@Joey_Rivera這個模式已經被doctrine實現了,如果在查詢時需要性能,我會使用它,我的問題是相反的。我不需要添加更多的對象引用,我需要一種方法來減少引用計數。 –

2

30.000對象水合物是相當多的。 Doctrine 2是穩定的,但有一些錯誤,所以我對你的內存泄漏問題並不感到驚訝。

儘管使用較小的數據集,我已經使用原則batch processing功能取得了一些成功並創建了可迭代的結果。

您可以使用示例中的代碼,並在每次迭代後添加gc_collect_cycles()。你必須對它進行測試,但對於我來說大約100個左右的批量大小工作得相當不錯 - 這個數字在性能和內存使用率之間取得了很好的平衡。

腳本識別哪些實體在哪裏進行處理是非常重要的,以便可以在沒有任何問題的情況下重新啓動它,並且在不發送電子郵件兩次的情況下恢復正常操作。

$batchSize = 20; 
$i = 0; 
$q = $em->createQuery('select u from MyProject\Model\User u'); 
$iterableResult = $q->iterate(); 
while (($row = $iterableResult->next()) !== false) { 
    $entity = $row[0]; 

    // do stuff with $entity here 
    // mark entity as processed 

    if (($i % $batchSize) == 0) { 
     $em->flush(); 
     $em->clear(); 

     gc_collect_cycles(); 
    } 
    ++$i; 
} 

無論如何,也許你應該重新考慮你的架構,該腳本一點,作爲一個ORM是不是很適合處理大量的數據。也許你可以逃避處理原始SQL行?

相關問題