這篇文章主要介紹PHP垃圾回收機制的相關問題,有興趣的朋友參考下,希望對大家有幫助。
PHP的基本GC概念PHP語言同其他語言一樣,具有垃圾回收機制。那麼今天我們要為大家講解的內容就是關於PHP垃圾回收機制的相關問題。希望對大家有幫助。 PHP strtotime應用經驗之談PHP memory_get_usage()管理記憶體PHP unset全域變數運用問題詳談PHP unset()函數銷毀變數教你快速實作PHP全站權限驗證一、PHP 垃圾回收機制(Garbage Collector 簡稱GC) 在PHP中,沒有任何變數指向這個物件時,這個物件就變成垃圾。 PHP會將其在記憶體中銷毀;這是PHP的GC垃圾處理機制,防止記憶體溢出。當一個PHP執行緒結束時,目前佔用的所有記憶體空間都會被銷毀,目前程式中所有物件同時被銷毀。 GC程序一般都跟著每起一個SESSION而開始運行的.gc目的是為了在session文件過期以後自動銷毀刪除這些文件.二、__destruct /unset __destruct() 析構函數,是在垃圾對像被回收時執行。
unset 銷毀的是指向物件的變量,而不是這個物件。三、 Session 與PHP垃圾回收機制由於PHP的工作機制,它並沒有一個daemon線程來定期的掃描Session信息並判斷其是否失效,當一個有效的請求發生時,PHP 會根據全局變量session.gc_probability和session .gc_pisor的值,來決定是否啟用一個GC, 在預設情況下,session.gc_probability=1, session.gc_pisor =100也就是說有1%的可能性啟動GC(也就是說100個請求中只有一個gc會伴隨100個中的某個請求而啟動).PHP垃圾回收機制的工作就是掃描所有的Session信息,用當前時間減去session最後修改的時間,同session.gc_maxlifetime參數進行比較,如果生存時間超過gc_maxlifetime (預設24分鐘),就將該session刪除。
但是,如果你Web伺服器有多個站點,多個站點時,GC處理session可能會出現意想不到的結果,原因就是:GC在工作時,並不會區分不同站點的session.那麼這個時候怎麼解決呢?
1. 修改session.save_path,或使用session_save_path()讓每個站點的session保存到一個專用目錄,
2. 提供GC的啟動率,自然,PHP垃圾回收機制的啟動率提高,系統的性能也會隨之減低,不建議。
3. 在程式碼中判斷目前session的生存時間,利用session_destroy()刪除。
引用計數基本知識每個php變數存在一個叫做"zval"的變數容器中.一個zval變數容器,除了包含變數的型別和值,還包括兩個位元組的額外資訊.第一個是"is_ref",是個bool值,用來識別這個變數是否是屬於引用集合(reference set).透過這個位元組,php引擎才能把普通變數和引用變數區分開.由於php允許使用者透過使用&來使用自訂引用,zval變數容器中還有一個內部引用計數機制,來優化記憶體使用.第二個額外位元組是"refcount",用來表示指向這個zval變數容器的變數(也稱符號即symbol)個數.
當一個變數被賦常量值時,就會產生一個zval變數容器,如下例所示:
<?php $a = "new string"; ?>
在上例中,新的變數是a,是在當前作用域中生成的.並且產生了類型為string和值為"new string"的變數容器.在額外的兩個位元組資訊中,"is_ref"被預設為false,因為沒有任何自訂的引用生成."refcount"被設定為1,因為這裡只有一個變數使用這個變數容器.呼叫xdebug查看變數內容:
<?php $a = "new string"; xdebug_debug_zval('a'); ?>
#以上程式碼會輸出:
a: (refcount=1, is_ref=0)='new string'
對變數a增加一個引用計數
<?php $a = "new string"; $b = $a; xdebug_debug_zval('a'); ?>
以上程式碼會輸出:
a: (refcount=2, is_ref=0)='new string'
這時,引用次數是2,因為同一變數容器被變數a和變數b關聯.當沒必要時,php不會去複製已產生的變數容器.變數容器在"refcount"變成0時就被銷毀.當任何關聯到某個變數容易的變數離開它的作用域(例如:函數執行結束),或是對變數呼叫了unset()函數,"refcount"就會減1,下面例子就能說明:
<?php $a = "new string"; $b = $c = $a; xdebug_debug_zval('a'); unset($b, $c); xdebug_debug_zval('a'); ?>
以上程式碼會輸出:
a: (refcount=3, is_ref=0)='new string' a: (refcount=1, is_ref=0)='new string'
如果我們現在執行unset($a),$包含的類型和值的這個容器就會從記憶體刪除
複合類型(compound types)
當考慮像array和object這樣的複合類型時,事情會稍微有些複雜.與標量(scalar)類型的值不同,array和object類型的變數把它們的成員或屬性存在自己的符號表中.這意味著下面的例子將產生三個zval變數容器
<?php $a = array('meaning' => 'life', 'number' => 42); xdebug_debug_zval('a'); ?>
以上程式碼輸出:
a: (refcount=1, is_ref=0)=array ('meaning' => (refcount=1, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42)
這三個zval變數容器是:a,meaning,number.增加和減少refcount的規則和上面提到的一樣
特例,添加數組本身作為數組元素時:
<?php $a = array('one'); $a[] = &$a; xdebug_debug_zval('a'); ?>
以上程式碼輸出的結果:
a: (refcount=2, is_ref=1)=array (0 => (refcount=1, is_ref=0)='one', 1 => (refcount=2, is_ref=1)=...)
可以看到数组a和数组本身元素a[1]指向的变量容器refcount为2
当对数组$a调用unset函数时,$a的refcount变为1,发生了内存泄漏
清理变量容器的问题尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),由于数组元素"1"仍然指向数组本身,所以这个容器不能被消除.因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏.庆幸的是,php将在请求结束时清除这个数据结构,但是php清除前,将耗费不少内存空间
回收周期5.3.0PHP使用了新的同步周期回收算法,来处理上面所说的内存泄漏问题
首先,我们先要建立一些基本规则:
如果一个引用计数增加,它将继续被使用,当然就不再垃圾中.如果引用技术减少到零,所在的变量容器将被清除(free).就是说,仅仅在引用计数减少到非零值时,才会产生垃圾周期(grabage cycle).其次,在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾
为避免不得不检查所有引用计数可能减少的垃圾周期,这个算法把所有可能根(possible roots 都是zval变量容器),放在根缓冲区(root buffer)中(用紫色标记),这样可以同时确保每个可能的垃圾根(possible garbage root)在缓冲区只出现一次.仅仅在根缓冲区满了时,才对缓冲区内部所有不同的变量容器执行垃圾回收操作。
总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。
相关推荐:
以上是PHP垃圾回收機制的相關問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!