2012-04-20 31 views
0

我有一段相當長的內存密集循環。我無法一次運行它,因爲我的服務器放置了執行的時間限制,或者我的內存不足。如何將一段非常長的內存密集的循環分割爲更小的塊

我想把這個循環分成更小的塊。

我靈機一動分裂環成小塊,然後設置一個位置標頭重新加載新的啓動條件的腳本。

我的老SCRIPT(僞代碼。我知道下面的缺點)

for($i=0;$i<1000;$i++) 
{ 
    //FUNCTION 
} 

MY NEW SCRIPT

$start=$_GET['start']; 
$end=$start+10; 

for($i=$start;$i<$end;$i++;) 
{ 
    //FUNCTION 
} 

header("Location:script.php?start=$end"); 

然而,我的新的腳本成功運行了幾次迭代,然後我獲得服務器錯誤「太多的重定向」

有沒有辦法解決?有人可以提出更好的策略嗎?

我是一個共享的服務器上,所以我不能增加內存分配或腳本的執行時間。

我想要一個PHP解決方案。

謝謝。

+0

難說不知道你的循環做什麼。你能發佈更多的代碼嗎? – Jack 2012-04-20 03:19:01

+0

PHP真的很糟糕,垃圾收集。最近有很多建議和對基本代碼的改進(包括一個新的GC庫),但是我已經對它們全部進行了修改,並且在某些情況下,PHP不會清除內存,不管有多少個unset或睡覺你做。嘗試給出的各種答案,但請注意,如果沒有人能夠正常工作,那麼您可能會將頭靠在牆上。 – Anthony 2012-04-20 03:28:59

+0

你的循環包含sql查詢嗎? – denil 2012-04-20 04:59:51

回答

0

首先,不知道你的內循環做,這是很難告訴你最好的辦法真正解決您的問題。但是,如果你想執行一些需要很長時間的事情,我的建議是設置一個cron作業,並讓它一次指出一小部分。該腳本會記錄停止位置,並在下次啓動時讀取日誌從哪裏開始。


編輯:如果你是堅決反對的cron,你是不是太在意用戶體驗,你可以這樣做:

讓類似於上面的cron作業頁面加載。除了這麼多秒或迭代之後,停止腳本。顯示刷新元標記或JavaScript刷新。做到這一點,直到任務完成。

+0

謝謝湯姆,循環內的腳本不是問題。它可以是任何東西。重要的是,它是時間和內存密集的本質,而不是糟糕的設計。對於這個應用程序來說,一個cron作業可能是過度的。該腳本只有我的服務器配置標準纔是時間和內存密集型的。它應該只需要2或3分鐘運行。我可以簡單地將標題更改爲下一個塊的鏈接,只需點擊它40次,但我希望能夠方便自動地運行它。 – Matt 2012-04-20 03:28:52

+0

元刷新/ JavaScript刷新會自動發生。如果這不是你想要的,像Clay Hinson所說的那樣查看分叉。 – teynon 2012-04-20 04:11:09

0

一般來說,如果我要過的東西很多很多次迭代,並在有數據的一個體面的數額,我用一個「懶加載」類型的應用程序,如:

for($i=$start;$i<$end;$i++;) 
{ 
    $data_holder[] = "adding my big data chunks!"; 
    if($i % 5 == 1){ 
    //function to process data 
    process_data($data_holder); // process that data like a boss! 
    unset($data_holder); // This frees up the memory 
    } 
} 

// Now pick up the stragglers of whatever is left in the data chunk 
if(count($data_holder) > 0){ 
    process_data($data_holder); 
} 

這樣,您可以繼續通過迭代你的數據,但你沒有填滿你的記憶。您可以分塊工作,然後取消設置數據,分塊工作,取消設置數據等,以幫助防止內存。就執行時間而言,這取決於你必須做多少/腳本的寫入效率。

的基本前提 - 「過程小塊數據,以避免內存問題,讓您的設計簡單,以保持它的快。」

+0

乾杯,這絕對有助於解決記憶問題。但在某些情況下,我仍然會遇到腳本執行時間限制問題。 – Matt 2012-04-20 04:32:39

+0

@Matt,嘗試將'set_time_limit(0);'插入到模數if語句中。您可能無法更改執行時間,但您可能會想到執行時間已經開始。讚賞有用的讚賞,選擇作爲答案,如果它是最適用/有益的更多讚賞;) – Blake 2012-04-20 04:36:58

0

你如何在循環中放置一個條件來每100次迭代一次?

for ($i = 0; $i < 1000; $i++) 
{ 
    if ($i % 100 == 0) 
     sleep(1800) //Sleep for half an hour 
} 
0

你可能想看看forking child processes做這項工作。這些子進程可以在他們自己的內存空間中以更小的塊進行工作,而父進程則會關閉多個子進程。這通常由Gearman處理,但是可以不用。

查看Dealnews的開發人員網站上的Forking PHP。它有一個庫和一些示例代碼來幫助管理需要產生子進程的代碼。

2

「太多重定向」是一個瀏覽器錯誤,所以PHP解決方案將使用cURL或標準流來加載初始頁面並讓它跟隨所有重定向。你必須從一臺沒有超時限制的機器上運行它(例如使用CLI)

要考慮的另一件事是使用AJAX。頁面上的一段JavaScript將運行腳本,收集腳本中的輸出並確定是停止(計算結束)還是繼續(從X開始)。這樣你也可以創建一個漂亮的進度表;-)

0

由於你有限制,我認爲你使用的方法可以工作。這可能是因爲你的瀏覽器試圖變得聰明,而不是讓你重定向你剛纔的頁面。它可能試圖阻止無限循環。

你可以嘗試

  • 兩個腳本是相同的(或別名)之間重來回。

  • 不同的瀏覽器。

  • 讓腳本輸出帶有刷新標記的HTML頁面,例如

    <meta http-equiv="refresh" content="1; url=http://example.com/script.php?start=xxx">

+0

嘿,那有效。我從來不知道你可以設置刷新標籤的URL。它不像我想要的那樣流暢,但它完成了工作。 – Matt 2012-04-20 04:34:06

+0

我寧願說「修好車」。比「但如果我把它從懸崖上推下去,它仍然可以走55!」 – Blake 2012-04-20 04:48:45

+0

@Blake,我同意你的看法,但請參閱「你有限制」和「但它完成了工作。」 – bmb 2012-04-20 05:36:13

相關問題