PHP內(nèi)存管理機(jī)制
var_dump(memory_get_usage()); //獲取內(nèi)存
$a = "laruence"; //定義一個(gè)變量
var_dump(memory_get_usage()); //定義變量之后獲取內(nèi)存
unset($a); //刪除該變量
var_dump(memory_get_usage()); //刪除變量后獲取內(nèi)存
打印結(jié)果
int 262144
int 262144
int 262144
從上面可以看出php的內(nèi)存管理機(jī)制是:預(yù)先給出一塊空間,用來(lái)存儲(chǔ)變量,當(dāng)空間不夠時(shí),再申請(qǐng)一塊新的空間。
1.存儲(chǔ)變量名,存在符號(hào)表。
2.變量值存儲(chǔ)在內(nèi)存空間。
3.在刪除變量的時(shí)候,會(huì)將變量值存儲(chǔ)的空間釋放,而變量名所在的符號(hào)表不會(huì)減小。
var_dump(memory_get_usage()); //獲取內(nèi)存
//定義100個(gè)變量
for($i=0;$i<100;$i++)
{ $a = "test".$i;
$a = "hello";
} //獲取定義100個(gè)變量之后的內(nèi)存
var_dump(memory_get_usage()); //定義100個(gè)變量并刪除
for($i=0;$i<100;$i++)
{ $a = "test".$i; unset($a);
} //獲取刪除之后的內(nèi)存
var_dump(memory_get_usage());</pre>
打印
int 240040
int 257680
int 240856
從上面可以看出,雖然刪除后內(nèi)存變小了,但還是比沒(méi)定義變量之前時(shí)大,這是因?yàn)殡m然刪除了變量的值,但變量名沒(méi)有被刪除。
php垃圾回收機(jī)制
PHP變量存儲(chǔ)是存儲(chǔ)在一個(gè)zval容器里面的
1.類(lèi)型 2.值 3.is_ref 代表是否有地址引用 4.refcount 指向該值的變量數(shù)量
1.變量賦值的時(shí)候:is_ref為false refcount為1
$a = 1;
xdebug_debug_zval('a');
echo PHP_EOL;
打印結(jié)果
(refcount=1, is_ref=0),int 1
2.將變量a的值賦給變量b,變量b不會(huì)立刻去在內(nèi)存中存儲(chǔ)值,而是先指向變量a的值,一直到變量a有任何操作的時(shí)候
$b = $a;
xdebug_debug_zval('a');
echo PHP_EOL;
打印結(jié)果
(refcount=2, is_ref=0), int 1
3.因?yàn)槌绦蛴植僮髁俗兞縜,所以變量b會(huì)自己申請(qǐng)一塊內(nèi)存將值放進(jìn)去。所以變量a的zavl容器中refcount會(huì)減1變?yōu)?,變量c指向a,所以refcount會(huì)加1變?yōu)?
$c = &$a;
xdebug_debug_zval('a'); echo PHP_EOL;
xdebug_debug_zval('b'); echo PHP_EOL;
垃圾回收:
1.在5.2版本或之前版本,PHP會(huì)根據(jù)refcount值來(lái)判斷是不是垃圾
如果refcount值為0,PHP會(huì)當(dāng)做垃圾釋放掉
這種回收機(jī)制有缺陷,對(duì)于環(huán)狀引用的變量無(wú)法回收
2.在5.3之后版本改進(jìn)了垃圾回收機(jī)制
如果發(fā)現(xiàn)一個(gè)zval容器中的refcount在增加,說(shuō)明不是垃圾
如果發(fā)現(xiàn)一個(gè)zval容器中的refcount在減少,如果減到了0,直接當(dāng)做垃圾回收
如果發(fā)現(xiàn)一個(gè)zval容器中的refcount在減少,并沒(méi)有減到0,PHP會(huì)把該值放到緩沖區(qū),當(dāng)做有可能是垃圾的懷疑對(duì)象。
當(dāng)緩沖區(qū)達(dá)到了臨界值,PHP會(huì)自動(dòng)調(diào)用一個(gè)方法去遍歷每一個(gè)值,如果發(fā)現(xiàn)是垃圾就清理