亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

PHP 之 寫時復(fù)制介紹(Copy On Write)

2020-03-22 20:16:19
字體:
供稿:網(wǎng)友
在開始之前,我們可以先看一段簡單的代碼:復(fù)制代碼 代碼如下:
?php //例一
$foo = 1;
$bar = $foo;
echo $foo + $bar;
?
執(zhí)行這段代碼,會打印出數(shù)字2。從內(nèi)存的角度來分析一下這段代碼“可能”是這樣執(zhí)行的:分配一塊內(nèi)存給foo變量,里面存儲一個1; 再分配一塊內(nèi)存給bar變量,也存一個1,最后計算出結(jié)果輸出。事實上,我們發(fā)現(xiàn)foo和bar變量因為值相同,完全可以使用同一塊內(nèi)存,這樣,內(nèi)存的使用就節(jié)省了一個1,并且,還省去了分配內(nèi)存和管理內(nèi)存地址的計算開銷。沒錯,很多涉及到內(nèi)存管理的系統(tǒng),都實現(xiàn)了這種相同值共享內(nèi)存的策略:寫時復(fù)制很多時候,我們會因為一些術(shù)語而對其概念產(chǎn)生莫測高深的恐懼,而其實,他們的基本原理往往非常簡單。本小節(jié)將介紹PHP中寫時復(fù)制這種策略的實現(xiàn):寫時復(fù)制(Copy on Write,也縮寫為COW)的應(yīng)用場景非常多, 比如Linux中對進(jìn)程復(fù)制中內(nèi)存使用的優(yōu)化,在各種編程語言中,如C++的STL等等中均有類似的應(yīng)用。 COW是常用的優(yōu)化手段,可以歸類于:資源延遲分配。只有在真正需要使用資源時才占用資源, 寫時復(fù)制通常能減少資源的占用。 注: 為節(jié)省篇幅,下文將統(tǒng)一使用COW來表示“寫時復(fù)制”;推遲內(nèi)存復(fù)制的優(yōu)化 正如前面所說,PHP中的COW可以簡單描述為:如果通過賦值的方式賦值給變量時不會申請新內(nèi)存來存放新變量所保存的值,而是簡單的通過一個計數(shù)器來共用內(nèi)存,只有在其中的一個引用指向變量的值發(fā)生變化時才申請新空間來保存值內(nèi)容以減少對內(nèi)存的占用。在很多場景下PHP都COW進(jìn)行內(nèi)存的優(yōu)化。比如:變量的多次賦值、函數(shù)參數(shù)傳遞,并在函數(shù)體內(nèi)修改實參等。下面讓我們看一個查看內(nèi)存的例子,可以更容易看到COW在內(nèi)存使用優(yōu)化方面的明顯作用:復(fù)制代碼 代碼如下:
?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());

//-----執(zhí)行結(jié)果-----
$ php t.php
int(630904)
int(10479840)
int(10479944)
int(10480040)
上面的代碼比較典型的突出了COW的作用,在數(shù)組變量$tipi被賦值給$tipi_copy時,內(nèi)存的使用并沒有立刻增加一半,在循環(huán)遍歷數(shù)$tipi_copy時也沒有發(fā)生顯著變化,在這里$tipi_copy和$tipi變量的數(shù)據(jù)共同指向同一塊內(nèi)存,而沒有復(fù)制。 也就是說,即使我們不使用引用,一個變量被賦值后,只要我們不改變變量的值 ,也不會新申請內(nèi)存用來存放數(shù)據(jù)。據(jù)此我們很容易就可以想到一些COW可以非常有效的控制內(nèi)存使用的場景:只是使用變量進(jìn)行計算而很少對其進(jìn)行修改操作,如函數(shù)參數(shù)的傳遞,大數(shù)組的復(fù)制等等等不需要改變變量值的情形。復(fù)制分離變化的值 多個相同值的變量共用同一塊內(nèi)存的確節(jié)省了內(nèi)存空間,但變量的值是會發(fā)生變化的,如果在上面的例子中,指向同一內(nèi)存的值發(fā)生了變化(或者可能發(fā)生變化),就需要將變化的值“分離”出去,這個“分離”的操作,就是“復(fù)制”。 在PHP中,Zend引擎為了區(qū)別同一個zval地址是否被多個變量共享,引入了ref_count和is_ref兩個變量進(jìn)行標(biāo)識:復(fù)制代碼 代碼如下:
ref_count和is_ref是定義于zval結(jié)構(gòu)體中(見第一章第一小節(jié))
is_ref標(biāo)識是不是用戶使用 & 的強(qiáng)制引用;
ref_count是引用計數(shù),用于標(biāo)識此zval被多少個變量引用,即COW的自動引用,為0時會被銷毀;
關(guān)于這兩個變量的更多內(nèi)容,跳轉(zhuǎn)閱讀:第三章第六節(jié):變量的賦值和銷毀的實現(xiàn)。
注:由此可見, $a=$b; 與 $a= 在PHP對內(nèi)存的使用上沒有區(qū)別(值不變化時);
下面我們把例二稍做變化:如果$copy的值發(fā)生了變化,會發(fā)生什么?:復(fù)制代碼 代碼如下:
?php //例三
//$tipi = array_fill(0, 3, 'php-internal');
//這里不再使用array_fill來填充 ,為什么?
$tipi[0] = 'php-internal';
$tipi[1] = 'php-internal';
$tipi[2] = 'php-internal';
var_dump(memory_get_usage());

$copy = $tipi;
xdebug_debug_zval('tipi', 'copy');
var_dump(memory_get_usage());

$copy[0] = 'php-internal';
xdebug_debug_zval('tipi', 'copy');
var_dump(memory_get_usage());

//-----執(zhí)行結(jié)果-----
$ php t.php
int(629384)
tipi: (refcount=2, is_ref=0)=array (0 = (refcount=1, is_ref=0)='php-internal',
1 = (refcount=1, is_ref=0)='php-internal',
2 = (refcount=1, is_ref=0)='php-internal')
copy: (refcount=2, is_ref=0)=array (0 = (refcount=1, is_ref=0)='php-internal',
1 = (refcount=1, is_ref=0)='php-internal',
2 = (refcount=1, is_ref=0)='php-internal')
int(629512)
tipi: (refcount=1, is_ref=0)=array (0 = (refcount=1, is_ref=0)='php-internal',
1 = (refcount=2, is_ref=0)='php-internal',
2 = (refcount=2, is_ref=0)='php-internal')
copy: (refcount=1, is_ref=0)=array (0 = (refcount=1, is_ref=0)='php-internal',
1 = (refcount=2, is_ref=0)='php-internal',
2 = (refcount=2, is_ref=0)='php-internal')
int(630088)
在這個例子中,我們可以發(fā)現(xiàn)以下特點:$copy = $tipi;這種基本的賦值操作會觸發(fā)COW的內(nèi)存“共享”,不會產(chǎn)生內(nèi)存復(fù)制;COW的粒度為zval結(jié)構(gòu),由PHP中變量全部基于zval,所以COW的作用范圍是全部的變量,而對于zval結(jié)構(gòu)體組成的集合(如數(shù)組和對象等),在需要復(fù)制內(nèi)存時,將復(fù)雜對象分解為最小粒度來處理。這樣可以使內(nèi)存中復(fù)雜對象中某一部分做修改時,不必將該對象的所有元素全部“分離復(fù)制”出一份內(nèi)存拷貝;復(fù)制代碼 代碼如下:
array_fill()填充數(shù)組時也采用了COW的策略,可能會影響對本例的演示,感興趣的讀者可以 閱讀:$PHP_SRC/ext/standard/array.c中PHP_FUNCTION(array_fill)的實現(xiàn)。

xdebug_debug_zval()是xdebug擴(kuò)展中的一個函數(shù),用于輸出變量在zend內(nèi)部的引用信息。 如果你沒有安裝xdebug擴(kuò)展,也可以使用debug_zval_dump()來代替。 參考:http://www.php.net/manual/zh/function.debug-zval-dump.php
實現(xiàn)寫時復(fù)制 看完上面的三個例子,相信大家也可以了解到PHP中COW的實現(xiàn)原理: PHP中的COW基于引用計數(shù)ref_count和is_ref實現(xiàn),多一個變量指針,就將ref_count加1, 反之減去1,減到0就銷毀;同理,多一個強(qiáng)制引用&,就將is_ref加1,反之減去1。這里有一個比較典型的例子:復(fù)制代碼 代碼如下:
?php //例四
$foo = 1;
xdebug_debug_zval('foo');
$bar = $foo;
xdebug_debug_zval('foo');
$bar = 2;
xdebug_debug_zval('foo');
?
//-----執(zhí)行結(jié)果-----
foo: (refcount=1, is_ref=0)=1
foo: (refcount=2, is_ref=0)=1
foo: (refcount=1, is_ref=0)=1
經(jīng)過前面對變量章節(jié)的介紹,我們知道當(dāng)$foo被賦值時,$foo變量的值的只由$foo變量指向。當(dāng)$foo的值被賦給$bar時,PHP并沒有將內(nèi)存復(fù)制一份交給$bar,而是把$foo和$bar指向同一個地址。同時引用計數(shù)增加1,也就是新的2。隨后,我們更改了$bar的值,這時如果直接需該$bar變量指向的內(nèi)存,則$foo的值也會跟著改變。這不是我們想要的結(jié)果。于是,PHP內(nèi)核將內(nèi)存復(fù)制出來一份,并將其值更新為賦值的:2(這個操作也稱為變量分離操作),同時原$foo變量指向的內(nèi)存只有$foo指向,所以引用計數(shù)更新為:refcount=1。 看上去很簡單,但由于&運(yùn)算符的存在,實際的情形要復(fù)雜的多。見下面的例子:


圖6.6 &操作符引起的內(nèi)存復(fù)制分離 從這個例子可以看出PHP對&運(yùn)算符的一個容易出問題的處理:當(dāng) $beauty= 時,兩個變量本質(zhì)上都變成了引用類型,導(dǎo)致看上去的普通變量$pan, 在某些內(nèi)部處理中與&$pan行為相同,尤其是在數(shù)組元素中使用引用變量,很容易引發(fā)問題。(見最后的例子) PHP的大多數(shù)工作都是進(jìn)行文本處理,而變量是載體,不同類型的變量的使用貫穿著PHP的生命周期,變量的COW策略也就體現(xiàn)了Zend引擎對變量及其內(nèi)存處理,具體可以參閱源碼文件相關(guān)的內(nèi)容:復(fù)制代碼 代碼如下:
Zend/zend_execute.c
========================================
zend_assign_to_variable_reference();
zend_assign_to_variable();
zend_assign_to_object();
zend_assign_to_variable();

//以及下列宏定義的使用
Zend/zend.h
========================================
#define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z))
#define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc)
#define Z_ADDREF(z) Z_ADDREF_P(&(z))
#define Z_DELREF(z) Z_DELREF_P(&(z))
#define Z_ISREF(z) Z_ISREF_P(&(z))
#define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z))
#define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z))
#define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref)
最后,請慎用引用& 引用和前面提到的變量的引用計數(shù)和PHP中的引用并不是同一個東西,引用和C語言中的指針的類似,他們都可以通過不同的標(biāo)示訪問到同樣的內(nèi)容,但是PHP的引用則只是簡單的變量別名,沒有C指令的靈活性和限制。 PHP中有非常多讓人覺得意外的行為,有些因為歷史原因,不能破壞兼容而選擇暫時不修復(fù),或者有的使用場景比較少。在PHP中只能盡量的避開這些陷阱。例如下面這個例子。 由于引用操作符會導(dǎo)致PHP的COW策略優(yōu)化,所以使用引用也需要對引用的行為有明確的認(rèn)識才不至于誤用,避免帶來一些比較難以理解的的Bug。如果您認(rèn)為您已經(jīng)足夠了解了PHP中的引用,可以嘗試解釋下面這個例子:復(fù)制代碼 代碼如下:
?php
$foo['love'] = 1;
$bar = &$foo['love'];
$tipi = $foo;
$tipi['love'] = '2';
echo $foo['love'];
這個例子最后會輸出 2 , 大家會非常驚訝于$tipi怎么會影響到$foo, $bar變量的引用操作,將$foo['love']污染變成了引用,從而Zend沒有對$tipi['love']的修改產(chǎn)生內(nèi)存的復(fù)制分離。PHP教程

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
羞羞色国产精品网站| 亚洲国产日日夜夜| 国产视频网站一区二区三区| 久久久久久久久久久免费视频| 无码人妻精品一区二区蜜桃色欲| 黄网免费视频| 久久av一区二区三区漫画| 国产资源在线看| 1024手机在线视频| 国产精品v欧美精品v日韩精品| 国产字幕在线看| 中文字幕高清一区| 午夜久久久久久久久久久| 欧美一区二区三区不卡视频| 网址你懂得在线观看| 羞羞电影在线观看www| 凹凸日日摸日日碰夜夜| 亚洲成人a**址| 国产乱色国产精品免费视频| 性欧美xxx极品另类| 一本色道久久加勒比精品| 成人精品影视| 桃花岛成人影院| 日本h片在线看| 超碰电影在线播放| 国产一区二区电影在线观看| 一级黄色大片免费看| 国产精品成人一区二区三区吃奶| 欧美人与z0zoxxxx特| 日本少妇高潮喷水xxxxxxx| 国产福利一区在线观看| 久久免费av| 欧美丝袜足交| 久久久久国产一区二区三区| 国产三级做爰高清在线| 亚洲欧洲精品视频| 最色在线观看| 伊人青青综合网| 在线观看91视频| 在线观看免费一区二区| 污视频网站在线免费观看| 欧美激情偷拍自拍| 欧美日韩电影免费看| 好吊操这里只有精品| 中文字幕第22页| 国产精品无码永久免费888| 国产福利一区二区| 国产一区中文字幕| 亚洲精品1区2区| 欧美精品一区二区三区很污很色的| 久久一区免费| 在线观看日韩www视频免费| 国产精品扒开腿做爽爽爽软件| 国产精品91一区| 亚洲一区精品视频在线观看| 男女羞羞视频网站| 亚洲wwwav| 97人人在线视频| av网站网址| 精品乱码亚洲一区二区不卡| 综合久久亚洲| **欧美日韩在线观看| 久久久久久国产精品无码| 三级av网站| 热re99久久精品国产99热| 99鲁鲁精品一区二区三区| 97人人爽人人喊人人模波多| **性色生活片久久毛片| 久久综合久久综合久久| 日韩一区二区三区高清在线观看| 亚洲综合伊人久久| 黄色毛片av| 一本在线高清不卡dvd| jizzjizz国产精品喷水| 成人爱爱电影网址| 精品中文字幕在线2019| 日韩欧美精品在线观看视频| 亚洲日本va在线观看| 欧美aaa在线观看| 97久久超碰福利国产精品…| 天天骑夜夜操| 亚洲国产精品一区二区第一页| 99久久精品国产色欲| 久久精品成人欧美大片| 黄色永久免费网站| 在线中文字幕播放| 国产精品视频xxx| 国产天堂av在线| 久久精品国产亚洲一区二区| 看黄的a网站| 视频在线不卡| 91麻豆精品成人一区二区| 国产麻豆视频在线观看| 免费观看亚洲| 国产精品黄色| 国产艳妇疯狂做爰视频| 九九热在线视频观看| av中文在线播放| 亚洲免费在线播放视频| 狠狠操五月天| 美女的诞生在线观看高清免费完整版中文| 亚洲精品网址在线观看| 久草免费在线观看视频| 成人性生交大免费看| 岛国电影中文在线| 午夜羞羞视频| 久久艳妇乳肉豪妇荡乳av| 色妞ww精品视频7777| 91精品国产黑色紧身裤美女| 欧美精品电影免费在线观看| 天堂中文在线www| 国产精品天天摸av网| 日韩一区二区高清视频| 国产精品亚洲а∨天堂免在线| 在线电影一区二区三区| 999国产精品永久免费视频app| 青娱乐在线视频免费观看| 色多多在线观看| 久久99亚洲网美利坚合众国| 亚洲精品免费在线观看视频| 亚洲伦片免费看| 欧美日韩福利在线观看| 国产精品大片wwwwww| 一区二区三区日韩欧美精品| 91在线观看入口| 国产资源一区| 少妇人妻偷人精品一区二区| 亚洲天天影视网| 国产激情在线观看| 国产精品1024久久| 欧美激情亚洲色图| 激情综合电影网| 日韩欧美久久| 老鸭窝av在线| 亚洲国产中文字幕在线观看| 99综合在线| 欧美亚洲禁片免费| 很黄很黄激情成人| 欧美激情网友自拍| 亚洲午夜精品国产| eeuss鲁片一区| 香蕉成人在线| 久久婷婷丁香| 国产ts在线播放| 四虎影视18库在线影院| 99精品视频免费在线观看| av中文字幕在线不卡| 免费在线你懂的| 亚洲天堂久久久久久久| 国产伦精品一区二区免费| 91久久精品| 亚洲欧美成人精品| 婷婷激情四射网| 精品一区二区三区五区六区七区| 日本a√在线观看| 免费在线欧美视频| 亚洲精品在线观看www| 国产一级成人av| 国产精品无码专区av在线播放| 欧美乱大交xxxxx潮喷l头像| 国产视频第一区| 日本精品va在线观看| 国产ts丝袜人妖系列视频| 日韩亚洲精品在线观看| 捆绑调教一区二区三区| 国产欧美日韩亚洲| 日韩三级电影网址| 激情成人午夜视频| 22288色视频在线观看| 免播放器亚洲| 国产九一精品| 欧美重口乱码一区二区| 欧美日韩在线免费| 日本欧美一区二区| 亚洲欧洲美洲一区二区三区| 中文字幕久久精品一区二区| 亚洲 欧美 视频| 5月婷婷6月丁香| 日韩一卡二卡三卡| 国产91久久精品一区二区| 天天干天天操天天爽| 裸体武打性艳史| 青草久久伊人| 香蕉视频官网在线观看日本一区二区| 永久免费看片视频教学| 国产在线一二| 五月婷婷久久丁香| 日韩经典在线视频| 亚洲精品国产精品国| 中文字幕在线永久在线视频2020| 国产午夜精品美女毛片视频| 亚洲tv在线观看| 日韩av电影一区| 91产国在线观看动作片喷水| 欧美有码在线| 青青草视频在线免费播放| 91精品国产综合久久精品| 国产无遮挡又黄又爽免费软件| 欧美日韩一二区| 午夜影院韩国伦理在线| 亚洲 日韩 国产第一区| 亚洲欧美一级二级三级| 国产又粗又长又爽又黄的视频| 免费污视频在线| 麻豆精品av| 免费不卡在线视频| 中文字幕激情小说| 在线观看成人小视频| 中文字幕理伦片免费看| 你懂的国产精品| 国产性生活网站| 69堂免费精品视频在线播放| 欧美女人性生活视频| av二区三区| 午夜在线观看免费一区| 国产精品va无码一区二区三区| 日本韩国一区二区三区视频| 成人免费观看视频大全| 亚洲人成网亚洲欧洲无码| 国产天堂在线播放视频| 狠狠综合久久av一区二区蜜桃| 日产精品99久久久久久| 在线无限看免费粉色视频| 四虎成人在线播放| 黑人巨大精品欧美一区二区奶水| 亚洲中文字幕久久精品无码喷水| palipali轻量版永久网页入口| 免费av片在线观看一道本| 国产精品成人一区二区三区| 国产精品日韩久久久| 成人18视频免费69| 亚洲精品视频在线观看网站| 日韩精品视频一区二区在线观看| 免费黄色一级大片| 92看片淫黄大片欧美看国产片| www.爱爱.com| 亚洲国产精品毛片av不卡在线| 日韩中文字幕亚洲| 顶级黑人搡bbw搡bbbb搡| 日韩理伦片在线| 日韩成人免费电影| 韩国精品一区二区三区| 青草在线视频| 亚洲影视一区二区三区| 在线看视频不卡| 男人av在线播放| 色哟哟视频在线| 三年片观看免费观看大全视频下载| 欧美老女人性视频| 国产精品国产三级国产aⅴ浪潮| **毛片在线网站| 99精品一区二区三区的区别| 精品在线视频一区| 欧美free性| 韩国三级在线一区| 97国产在线视频| 国产99久久久国产精品免费看| 狠狠色噜噜狠狠狠狠97| 国产精品传媒在线| 538任你躁在线精品视频网站| 日韩在线观看视频一区二区三区| 国产丝袜欧美中文另类| 亚洲丶国产丶欧美一区二区三区| 亚洲美女精品视频| 日韩电影免费观| 日韩欧美在线国产| 亚洲一区在线观看免费观看电影高清| 成人高清视频在线观看| 欧美日韩在线精品一区二区三区激情综合| 亚洲一区二区三区久久| 另类中文字幕国产精品| 亚洲免费在线视频一区 二区| 成人短视频在线观看免费| 日本一区视频在线| 搡女人真爽免费午夜网站| 久久99国产精品久久99果冻传媒| 国产在线高清视频| 黑人中文字幕一区二区三区| av一区和二区| 亚洲视频一区二区免费在线观看| 大伊香蕉精品视频在线| 精品国产二区三区| 波多野结衣激情| 女人18毛片水真多免费播放| 久久精品亚洲热| 国产精品久久久久久久久免费高清| 国产精品国产三级国产a| 成人免费短视频| 日韩欧美在线播放| 成人一级毛片| 性生交生活影碟片| 国产交换配乱淫视频免费| 国产成人一区二区三区电影| 欧美精品国产一区| 成人亚洲免费视频| 亚洲精品综合| 青青操在线观看| 91在线视频国产| av高清一区二区| 精品福利免费观看| 日本孕妇大胆孕交无码| 91在线视频精品| 韩国午夜理伦三级不卡影院| 亚洲国产精品一区二区久久| 欧美熟妇乱码在线一区| 99热这里精品| 手机看片福利盒子久久| www.热久久| 色老综合老女人久久久| 性欧美xxx极品另类| 日韩在线视频二区| 无码人妻丰满熟妇精品区| 日韩精品在线视频| 伊人75在线| 人妻丰满熟妇av无码久久洗澡| 国内免费久久久久久久久久久| aⅴ在线免费观看| 精品国产乱码久久久久久1区二区| www.精品av.com| 日韩av高清在线播放| 亲子乱一区二区三区电影| 免费a级毛片永久免费| 久久精品国产99国产精品澳门| 看电视剧不卡顿的网站| 日本强好片久久久久久aaa| 久久久久久人妻一区二区三区| 99产精品成人啪免费网站| 国产原创一区|