溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PHP寫時(shí)復(fù)制的案例分析

發(fā)布時(shí)間:2020-11-06 14:16:48 來源:億速云 閱讀:116 作者:小新 欄目:編程語言

這篇文章主要介紹了PHP寫時(shí)復(fù)制的案例分析,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

從一個(gè)例子說起:

<?php
$foo = 1;
$bar = $foo;
echo $foo + $bar;

變量 $foo 賦值給變量 $bar,這兩個(gè)變量具有相同的值,沒有必要新申請內(nèi)存空間,他們可以共享同一塊內(nèi)存。在很多場景下PHP 的 COW 對內(nèi)存進(jìn)行優(yōu)化。比如:變量的多次賦值、函數(shù)參數(shù)傳遞,并在函數(shù)體內(nèi)修改實(shí)參等。

什么是“復(fù)制”

這是一段摘自鳥哥博客的例子,說的比較清楚,就直接貼過來了。

<?php
   $var = "laruence";
   $var_dup = $var;
   $var = 1;
?>

很明顯在這段代碼執(zhí)行以后,$var_dup 的值應(yīng)該還是”laruence”, 那么這又是怎么實(shí)現(xiàn)的呢?這就是 PHP 的 copy on write 機(jī)制:

PHP 在修改一個(gè)變量以前,會(huì)首先查看這個(gè)變量的 refcount,如果 refcount 大于1,PHP 就會(huì)執(zhí)行一個(gè)分離的例程, 對于上面的代碼,當(dāng)執(zhí)行到第三行的時(shí)候,PHP 發(fā)現(xiàn) $var 指向的 zval 的 refcount 大于1,那么 PHP 就會(huì)復(fù)制一個(gè)新的 zval 出來,將原 zval 的 refcount 減 1,并修改 symbol_table,使得 $var 和 $var_dup 分離(Separation)。這個(gè)機(jī)制就是所謂的 copy on write(寫時(shí)復(fù)制)。

寫時(shí)復(fù)制應(yīng)用場景

寫時(shí)復(fù)制(Copy on Write,也縮寫為COW)的應(yīng)用場景非常多, 比如Linux中對進(jìn)程復(fù)制中內(nèi)存使用的優(yōu)化,在各種編程語言中,如C++的STL等等中均有類似的應(yīng)用。 COW是常用的優(yōu)化手段,可以歸類于:資源延遲分配。只有在真正需要使用資源時(shí)才占用資源, 寫時(shí)復(fù)制通常能減少資源的占用。

一個(gè)證明 PHP COW 優(yōu)化內(nèi)存占用的例子:

<?php
$j = 1;
var_dump(memory_get_usage());
 
$tipi = array_fill(0, 100000, 'php-internal');
var_dump(memory_get_usage());
 
$tipi_copy = $tipi;
var_dump(memory_get_usage());
 
foreach ($tipi_copy as $i) {
    $j += count($i);
}
var_dump(memory_get_usage());

運(yùn)行結(jié)果:

$ php t . php
int(630904)
int(10479840)
int(10479944)
int(10480040)

內(nèi)存并沒有顯著提高。

“寫時(shí)復(fù)制”的原理

多個(gè)相同值的變量共用同一塊內(nèi)存的確節(jié)省了內(nèi)存空間,但變量的值是會(huì)發(fā)生變化的,如果在上面的例子中, 指向同一內(nèi)存的值發(fā)生了變化(或者可能發(fā)生變化),就需要將變化的值“分離”出去,這個(gè)“分離”的操作, 就是“復(fù)制”。

在PHP中,Zend引擎為了區(qū)別同一個(gè)zval地址是否被多個(gè)變量共享,引入了ref_count和is_ref兩個(gè)變量進(jìn)行標(biāo)識:

ref_count和is_ref是定義于zval結(jié)構(gòu)體中

is_ref標(biāo)識是不是用戶使用 & 的強(qiáng)制引用;

ref_count是引用計(jì)數(shù),用于標(biāo)識此zval被多少個(gè)變量引用,即COW的自動(dòng)引用,為0時(shí)會(huì)被銷毀;

注:由此可見, $a=$b; 與 $a=&$b; 在PHP對內(nèi)存的使用上沒有區(qū)別(值不變化時(shí));

相信大家也可以了解到PHP中COW的實(shí)現(xiàn)原理: PHP 中的 COW 基于引用計(jì)數(shù)ref_count 和 is_ref 實(shí)現(xiàn), 多一個(gè)變量指針,就將 ref_count 加 1, 反之減去 1,減到 0 就銷毀; 同理,多一個(gè)強(qiáng)制引用 &,就將 is_ref 加 1,反之減去 1。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享PHP寫時(shí)復(fù)制的案例分析內(nèi)容對大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問題就找億速云,詳細(xì)的解決方法等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI