2011-03-20 86 views
7

我有一張地圖。在這張地圖上,我想顯示從幾個表中收集的實時數據,其中一些表的行數驚人。不用說,獲取這些信息需要花費很長的時間。此外,涉及ping。根據離線或遠離的服務器,這些數據的收集時間可能會在1到10分鐘之間變化。爲什麼連續運行PHP腳本這麼糟糕?

我希望地圖能夠快速響應,因此我決定向我的數據庫添加一個只包含地圖所需數據的新表。這意味着我需要一個後臺進程來不斷更新我的新表中的信息。 Cron工作當然是一種可能性,但我希望在前一個時間間隔完成後立即刷新數據。如果離線IP地址的數量突然增加,並且循環運行時間比Cron作業的時間間隔更長,會怎樣?

我自己的解決方案是在PHP中通過命令行創建一個無限循環。此循環會刷新映射到MySQL的數據,並記錄其他有用的數據,例如循環時間和Ping失敗嘗試等,然後在短暫停頓(幾秒鐘)後重新啓動。

但是 - 人們反覆告訴我,一個永遠運行的PHP腳本是壞的。經過一段時間後,它會消耗千兆字節的RAM(以及其他可怕的東西)

部分我正在寫這個問題來確認事實是否如此,但是關於如何去寫一個乾淨的東西的一些技巧和竅門循環不會泄漏內存(如果可能的話)不會出錯。關於這個問題的意見也將不勝感激。

我認爲這個問題的答案對我將標記爲正確的問題最爲重視。

+0

一個令人難以置信的小問題,但請不要添加簽名/簽收問題。 (除此之外,這是一個構建得非常好的問題。):-) – 2011-03-20 22:58:05

+0

對不起,謝謝:-) – Hubro 2011-03-20 23:03:54

回答

4

循環應該在一個腳本中,它將激活/調用實際的腳本作爲一個不同的過程...很像cron正在做的事情。
這樣,即使內存泄漏,並且未收集的內存正在累積,它在每個週期之後都應該是空閒的。

+0

我喜歡一個例子。你的意思是這樣嗎? http://pastebin.com/SJeq9Xge – Hubro 2011-03-20 23:10:45

2

但是 - 人們反覆告訴我,一個永遠運行的PHP腳本是壞的。經過一段時間後,它會消耗千兆字節的RAM(以及其他可怕的東西)

這曾經是非常真實的。以前的PHP版本有可怕的garbage collection,所以長時間運行的腳本很容易意外地消耗比實際使用的更多的內存。 PHP 5.3 introduced a new garbage collector可以理解和清理循環引用,這是「內存泄漏」的頭號原因。它默認啓用。查看更多信息和漂亮圖形的鏈接。

只要你的代碼採取措施允許變量在適當的時候超出範圍,否則取消設置不再使用的變量,你的腳本不應該因爲它是PHP而消耗不必要的內存量。

1

我不認爲它很糟糕,就像你想要連續運行的任何事情一樣,你必須更加小心。

有些圖書館可以幫助你完成任務。看看System_Daemon,它在一個月前發佈了RC 1,它允許您「設置最大RAM使用率等選項」。

1

而不是運行一個無限循環我會試着去與您提到的cron選項結合使用數據庫表項或平面文件來存儲「當前有效」狀態位以確保你沒有重疊的進程試圖同時運行。

雖然我知道這將意味着一個小延遲執行下一次迭代之前,這可能是一個更好的主意反正爲:

  1. 這將讓RDBMS執行任何未決低優先級更新等等,因爲您一直在進行的活動量很可能已被擱置。儘管最近的改進(5.2引入了一個新的內存管理系統和垃圾收集在5.3中進行了徹底檢查),但即使您整齊地取消了所有使用的臨時變量,PHP仍會「泄漏」內存,儘管如此,應該有希望的意思是這個問題較少。

一般情況下,它也將是比較容易處理的其他問題(如數據庫連接暫時下降由於配置改變和重新啓動的例子),如果你在一個理想的使用cron的辦法,雖然無論如何,你會在代碼中迎合這樣的可能性。 (也就是說,我上次檢查時,這遠遠不是一個理想的世界。)

+0

1.使用無限循環時,情況也不例外,只要每個間隔之間有一個暫停?就我而言,這個腳本無論如何都會在專用服務器上運行。 2.可以通過運行一個PHP文件來解決這個問題:當循環執行另一個PHP文件時,然後休息一下? – Hubro 2011-03-20 23:21:08

+0

@Codemonkey 1.是的。 2.理論上是。不過,我仍然覺得它不會那麼可靠。也就是說,在事實之後轉換你提到的使用cron的方法是很簡單的,所以這很可能是一條可行的路。 (即:嘗試PHP腳本以不同的「模式」方式產生其自身副本,並且如果這看起來隨着時間推移而降級,則只需通過cron調用相同的腳本)。只要定期記錄'memory_get_usage'的結果, memory_get_peak_usage'等,那麼應該很容易監控事情進展情況。 – 2011-03-21 07:56:22

0

首先我沒有看到你需要一個守護進程腳本來提供你描述的功能。

Cron作業當然是可能的,但我想數據的刷新儘快先前區間已完成

的既不是cron作業,也不是一個守護進程是解決方式發生該問題(除非守護進程成爲腳本的數據接收器)。當數據可用時使用鎖定策略來實現併發性,我會產生一個分離的進程。

長時間運行的PHP腳本本質上並不壞 - 但引用計數垃圾回收器並不處理清理內存的所有可能場景 - 但更近期的實現有更高級的收集器,它應該清理更多(循環引用檢查)。