php中變量存在于一個zval的變量容器中? ?結(jié)構(gòu):類型? ?值? ? is_ref? ? refcount
is_ref:是個bool值,用來區(qū)分變量是否屬于引用集合。什么意思呢黍氮,你可以這么認(rèn)為:表示變量是否有一個以上的別名
refcount:計數(shù)器,表示指向這個zval變量容器的變量個數(shù)
兩者之間有這么一個默認(rèn)關(guān)系:當(dāng)refcount值為1時,is_ref的值為false蜻拨。因為refcount為1,此變量不可能有多個別名桩引,也就不存在引用了
注意缎讼,將一個變量 = 賦值給另一個變量時,不會立即為新變量分配內(nèi)存空間坑匠,而是在原變量的zval中給refcount加1血崭。 只有當(dāng)原變量或者發(fā)生改變時,才會為新變量分配內(nèi)存空間,同時原變量的refcount減 1 夹纫。當(dāng)然咽瓷,如果unset原變量,新變量直接就使用原變量的zval而不是重新分配
&引用賦值時舰讹,原變量的is_ref 變?yōu)?忱详,refcount 加1. 如果給一個變量&賦值,之前 = 賦值的變量會分配空間
環(huán)狀引用
<?php?
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>
引擎在判斷一個變量空間是否能夠被釋放的時候是依據(jù)這個變量的zval的refcount的值跺涤,如果refcount為0匈睁,那么變量的空間可以被釋放,否則就不釋放桶错,這是一種非常簡單的GC實現(xiàn)
現(xiàn)在unset ($a),那么array的refcount減1變?yōu)?.現(xiàn)在無任何變量指向這個zval航唆,而且這個zval的計數(shù)器為1,不會回收
PHP5.3中院刁,采用了專門的算法(比較復(fù)雜)糯钙。,來處理環(huán)狀引用導(dǎo)致內(nèi)存泄露的問題退腥。
當(dāng)一個zval可能為垃圾時任岸,回收算法會把這個zval放入一個內(nèi)存緩沖區(qū)。當(dāng)緩沖區(qū)達(dá)到最大臨界值時(最大值可以設(shè)置)狡刘,回收算法會循環(huán)遍歷所有緩沖區(qū)中的zval享潜,判斷其是否為垃圾,并進(jìn)行釋放處理嗅蔬〗0矗或者我們在腳本中使用gc_collect_cycles,強(qiáng)制回收緩沖區(qū)中的垃圾。
在php5.3的GC(Garbage Collection)中澜术,針對的垃圾做了如下說明:
1:如果一個zval的refcount增加艺蝴,那么此zval還在使用,肯定不是垃圾鸟废,不會進(jìn)入緩沖區(qū)
2:如果一個zval的refcount減少到0猜敢, 那么zval會被立即釋放掉,不屬于GC要處理的垃圾對象盒延,不會進(jìn)入緩沖區(qū)缩擂。
3:如果一個zval的refcount減少之后大于0,那么此zval還不能被釋放兰英,此zval可能成為一個垃圾撇叁,將其放入緩沖區(qū)。PHP5.3中的GC針對的就是這種zval進(jìn)行的處理畦贸。
開啟/關(guān)閉垃圾回收機(jī)制可以通過修改php配置實現(xiàn)陨闹,也可以在程序中使用gc_enable() 和 gc_disable()開啟和關(guān)閉