2013-03-23 69 views
1

我有一個PHP腳本來取消一個網站(僅限文本文件)。運行幾個小時後,我注意到腳本停止達到內存限制。我知道我可以增加限制,但是由於腳本加載的文件是純文本HTML文件,我只解釋了在每次循環後腳本無法清空內存時才達到限制。我是否可以通過定期刷新內存來優化腳本的內存管理?PHP腳本內存限制和內存優化

+0

如果您顯示的代碼,也許有人可以發現內存不是free'd。 'flush()'用於處理輸出緩衝區。 – alex 2013-03-23 11:54:20

+0

請注意PHP版本號。內存管理在PHP 5.2及更早版本中有很大不同。 – cleong 2013-03-23 11:55:44

+0

我的問題與我的腳本無關。我只是想在概念上理解何時需要在代碼中明確釋放內存。 – CptNemo 2013-03-23 12:00:22

回答

1

您可以根據您不再需要的變量unset(例如unset($var)$var = null)。如果您使用的是PHP 5.3或更高版本,則還可以顯式調用垃圾收集器:請參閱gc_collect_cycles()和gc_enable()。

某些功能似乎比其他功能更差。我最近發現array_merge_recursive()對我的代碼的內存佔用做了可怕的事情。

如果您希望能夠分析內存正在運行的位置,則可以使用Xdebug或XHProf/XHGui等工具來提供幫助。例如Xdebug and tracing memory usageProfiling with XHProf

參見:

Force freeing memory in PHP

php garbage collection while script running

+1

請注意,PHP垃圾收集器僅用於**循環引用的特例;它不是** Zend引擎中的主要內存管理機制。 – IMSoP 2013-03-23 12:59:23

+0

是的,好的,@IMSoP。更多信息請登錄http://php.net/manual/en/features.gc.performance-considerations.php和http://php.net/manual/en/features.gc.collecting-cycles.php查看感興趣的人。 – 2013-03-23 13:49:31

3

一般情況下,你不應該需要PHP手工管理內存,因爲它內置了一個高層次的內存管理器到Zend引擎,爲你照顧這件事。但是,瞭解一下這個過程是如何工作的,以便更好地理解你的代碼爲什麼會耗盡內存是非常有用的。

由於是一個非常基本的概述,PHP根據有多少變量引用特定數據的「refcount」來釋放內存。因此,如果你說$a = 'hello'; $b = $a;,包含字符串'hello'的單個內存將有一個2的refcount。如果你調用unset()對任何變量,或者它們超出範圍(例如在它們被定義的函數的末尾),該人數將減少。一旦refcount達到零,數據將被刪除並釋放內存。請注意,在這種情況下,「釋放」意味着釋放該PHP腳本的其他部分使用,不一定會釋放回操作系統供其他進程使用。

有PHP版本價值之間的一些差異知道:

  • 如果你有循環引用上述引用計數機制不起作用(如$obj1->foo = $obj2; $obj2->bar = $obj1;)因爲引用計數永遠不會到達零。在PHP 5.2及更早版本中,這意味着這樣的循環引用導致內存泄漏,並且必須由程序員手動處理。在PHP 5.3中,"Garbage Collector"增加了專門處理這種情況。它不會取代正常的refcount機制,但是如果循環引用在您的代碼中很常見,那麼可能值得一讀。
  • PHP 5.4對PHP分配和使用內存的方式進行了大量優化。 AFAIK,這些都沒有改變如何編寫高效代碼的基本建議,只要你願意,它們只是升級你的PHP版本的一個很好的理由。

除此之外,還有編寫PHP代碼,使良好的使用內存的幾個常見提示:

  • 讓當不再需要確保未使用的變量被丟棄。在一個結構良好的程序中,這通常不是問題,因爲大多數變量對某個特定功能來說都是本地的;當函數退出時,它們將超出範圍,並被釋放。但是,如果您要創建大型中間變量,或動態創建大量變量,則手動調用unset()可能是個好主意。如果你的代碼是非常線性的,或者使用大量的全局變量和靜態變量,只需將它重構爲更加模塊化的結構就可以提高內存性能以及可讀性,可維護性等。
  • 指定或傳遞變量參考($foo = &$bar)可能導致PHP使用更多內存比直接分配($foo = $bar)。這是因爲PHP使用「Copy On Write」機制將具有相同內容的變量存儲在內存的一個位置,但引用分配與此機制衝突,因此PHP必須儘早複製該變量。
  • 對象比標量值(int,boolean,string)或數組更需要內存。這是PHP 5.4中已經大大改進的一件事情,但仍值得思考 - 儘管顯然不排除編寫結構良好的代碼!