2012-04-24 64 views
3

我試圖foreach通過數組中的許多千項,做一些操作並將一些值保存到mysql表。內存限制超過PHP foreach

但是,當我循環時,內存使用量會不斷增加,直到我用完php.ini中指定的內存爲止,這非常快。

我試過使用unset,將變量設置爲null並查看垃圾回收,但沒有任何影響。

有沒有一種更有效的方式來循環這些元素(即內存使用不會持續增長)。

下面是我正在做的一個簡單的例子。

foreach ($subscribers as $subscriber) 
{ 
    $member = new Member($subscriber['id']); 
    if ($member['id'] > 0) 
    { 
     $bulletin = Bulletin::getCustomBulletin($member['id']); 

     Bulletin::compileBulletin($member['email'], time(), $bulletin['title'], $bulletin['content']); 

     echo $member['email'] . "\n"; 
     echo memory_get_usage() . "\n"; 
    } 
} 

這將產生以下結果:

[email protected] 
11336688 
[email protected] 
12043640 
[email protected] 
12749952 
+0

你的php.ini中的內存限制是多少? – webbiedave 2012-04-24 15:07:16

+0

我已經將它從32MB移動到了512MB。我目前只在本地機器上進行測試。我知道在php.ini中做出的任何合理的選擇都會太小。 – 2012-04-24 15:10:26

+0

您是否嘗試用僅返回所需詳細信息的靜態查找函數替換成員對象實例化?您甚至可以嘗試用靜態數組替換該行,並查看是否仍然存在問題。 – 2012-04-24 15:12:49

回答

0

有沒有什麼可疑的有關foreach循環(不變量,因爲他們都被寫在每個迭代中未設置)。你將需要找出哪一行導致內存抓取。在專業IDE中找到的分析器會對此有所幫助。如果你沒有權限訪問,你會像以前一樣使用memory_get_usage(),但將其放在每一行後面以檢查哪一個導致了瓶頸。

還有免費的分析工具,如xdebug

+0

我安裝了xdebug和webgrind。不幸的是,它似乎並沒有顯示哪些功能花費最多的時間。 我懷疑我需要找到一種完全實現這一點的新方法,即處理一組較小的數據。 – 2012-04-24 15:18:17

1

$suscribers DB查詢的結果嗎?

如果是這樣,它可能是問題的根源:即使您一次只檢查一行,它們也會緩存在內存中。

您可以嘗試使用unbuffered queries或限制查詢結果的數量並執行幾個較小的查詢。

參見:Why "Allowed memory size exhausted"?

+0

是的。它作爲一項操作並不是特別昂貴,即只爲每個用戶提供一個id密鑰和一個id。你會說什麼是執行幾個較小操作的好方法?我試過了一個for循環,我在每個循環中更新一個偏移量和一個限制,但是這導致內存管理沒有改進。 – 2012-04-24 15:26:29

+0

@AndyTait是的,這是我的建議,如果它不起作用,那可能不是它(它在類似的問題上爲我工作)。你是否獲取了很多'$ suscribers'? – 2012-04-24 15:29:08

+0

是的,我抓住10K + – 2012-04-24 15:30:39

0

遺憾的是很難從自己張貼,因爲沒有線索,以什麼成員對象內部代碼是否告訴,但是這看起來是一個可能:

recursive references leak memory

我會消除在上面的代碼中創建新的成員對象來檢查是否是內存泄漏的來源。從你所說的話來說,創建成員對象可能是不必要的,它可以被靜態查找成員函數替代。

+0

問題是,Bulletin :: getCustomBulletin()和Bulletin :: compileBulletin()中有數百行代碼。所以我認爲我需要找到一種在循環周圍每次迭代後消除吞噬內存的方法。 – 2012-04-25 07:35:18

+0

我認爲這些都很好,但如果在'Member'類中有任何對其他對象的引用,那麼當你在循環中創建新的成員對象時,內存將不會被釋放。在'Member'類中寫一個靜態成員函數來獲取這個循環所需的細節是值得的。 'Member :: getMemberDetails($ subscriber ['id'])'靜態調用應該沒問題,這就是爲什麼不需要觸及Bulletin類。 – 2012-04-26 10:56:19