濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > PHP7內(nèi)核之Reference詳解

PHP7內(nèi)核之Reference詳解

熱門(mén)標(biāo)簽:十堰ai電話(huà)機(jī)器人效果怎么樣 地圖標(biāo)注風(fēng)向標(biāo) 上海公司外呼系統(tǒng)線(xiàn)路 臨沂智能電銷(xiāo)機(jī)器人軟件 銀川ai電話(huà)機(jī)器人 浙江外呼電話(huà)系統(tǒng)軟件 電梯外呼線(xiàn)路板維修視頻 安陽(yáng)自動(dòng)外呼系統(tǒng)價(jià)格是多少 芒果電銷(xiāo)機(jī)器人

問(wèn)題

上一章說(shuō)過(guò)引用(REFERENCE)在PHP5的時(shí)候是一個(gè)標(biāo)志位, 而在PHP7以后我們把它變成了一種新的類(lèi)型:IS_REFERNCE. 然而引用是一種很常見(jiàn)的應(yīng)用, 所以這個(gè)變化帶來(lái)了很多的變化, 也給我們?cè)谧鯬HP7開(kāi)發(fā)的時(shí)候, 因?yàn)橛械臅r(shí)候疏忽忘了處理這個(gè)類(lèi)型, 而帶來(lái)不少的bug.

最簡(jiǎn)單的情況, 就是在處理各種類(lèi)型的時(shí)候, 從此以后我們要多考慮這種新的類(lèi)型, 比如在PHP7中, 這樣的代碼形式就變得很常見(jiàn)了:

try_again:
swtich (Z_TYPE_P(zv)) {
   case IS_TRING:
   break;
   case IS_ARRAY:
   break;
  ...
   case IS_REFERENCE:
   zv = Z_REFVAL_P(zv); //解引用
   goto try_again;
   break;
}

如果大家自己寫(xiě)的擴(kuò)展, 如果忘了考慮這種新的類(lèi)型, 那么就會(huì)導(dǎo)致問(wèn)題.

為什么?
那么既然這種新類(lèi)型會(huì)帶來(lái)這么多問(wèn)題, 那么當(dāng)時(shí)為什么要用把引用變成一種類(lèi)型呢? 為什么不還是使用一個(gè)標(biāo)志位呢?

一句話(huà)來(lái)說(shuō), 就是我們不得不這么做. -_#

前面說(shuō)到, Hashtable直接存儲(chǔ)的是zval, 這樣在符號(hào)表中, 倆個(gè)zval如何共用一個(gè)數(shù)值呢? 對(duì)于字符串等復(fù)雜類(lèi)型來(lái)說(shuō)還好, 我們貌似可以在zend_refcounted結(jié)構(gòu)中加入一個(gè)標(biāo)志位來(lái)表明是引用來(lái)解決, 然而這個(gè)也會(huì)遇到Change On Write帶來(lái)的復(fù)制, 但是我們知道在PHP7中, 一些類(lèi)型是直接存儲(chǔ)在zval中的, 比如IS_LONG, 但是引用類(lèi)型是需要引用計(jì)數(shù)的, 那么對(duì)于一個(gè)是IS_LONG并且又是IS_REFERNCE的zval該如何表示呢?

為此, 我們創(chuàng)造了這個(gè)新的類(lèi)型:

 如圖所示, 引用是一種新的類(lèi)型:zend_reference, 對(duì)于IS_REFERNCE類(lèi)型的zval, zval.value.ref是一個(gè)指向zend_reference的指針, 它包含了引用計(jì)數(shù)和一個(gè)zval, 具體的zval的值是存在zval.value.ref->val中的.

所以對(duì)于IS_LONG的引用來(lái)說(shuō), 就用一個(gè)類(lèi)型是IS_REFERNCE的zval, 它指向一個(gè)zend_reference, 而這個(gè)zend_reference->val中是一個(gè)類(lèi)型為IS_LONG的zval.

Change On Write
PHP采用引用計(jì)數(shù)來(lái)做簡(jiǎn)單的垃圾回收, 考慮如下的代碼:

?php
1. $val = "laruence";
2. $ref = $val;
3. $copy = $val;
?>

$ref和$val是指向同一個(gè)zval的引用, 在PHP5的時(shí)候, 我們是通過(guò)一個(gè)引用計(jì)數(shù)為2, 并且引用標(biāo)志位為1來(lái)表示這種情況, 當(dāng)把$val復(fù)制給$copy(line 3)的時(shí)候, 我們發(fā)現(xiàn)$val是一個(gè)計(jì)數(shù)大于1的引用, 所以要產(chǎn)生Change on write, 也就是分離. 所以我們需要復(fù)制這個(gè)zval.

而在PHP7中, 情況就變得簡(jiǎn)單了很多, 首先在引用賦值給$ref(line 2)的時(shí)候, 生成一個(gè)IS_REFERNCE類(lèi)型, 然后因?yàn)榇藭r(shí)有倆個(gè)變量引用它所以zend_reference這個(gè)結(jié)構(gòu)的引用計(jì)數(shù)zval.value.ref->gc.refcount為2.

再隨后的賦值給$copy(line 3)的時(shí)候, 發(fā)現(xiàn)$val是一個(gè)引用, 于是讓$copy指向的是zval.value.ref->val, 也就是字符串值為laruence的zval, 然后把zval的引用計(jì)數(shù)+1, 也就是zval.value.ref->val.value.str.gc.refcount為2. 并沒(méi)有產(chǎn)生復(fù)制.

從而這就很好的解決了上一章所說(shuō)的PHP5的那個(gè)經(jīng)典的問(wèn)題, 比如我們?cè)赑HP7下運(yùn)行上一章的那個(gè)問(wèn)題, 我們得到的結(jié)果是:

$ php-7.0/sapi/cli/php /tmp/1.php
Used 0.00021380008539
Used 0.00020173048281

 可見(jiàn)確實(shí)沒(méi)有發(fā)生復(fù)制, 從而不會(huì)產(chǎn)生任何的性能問(wèn)題.

以上所述是小編給大家介紹的PHP7內(nèi)核之Reference詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

您可能感興趣的文章:
  • PHP7引入的"??"和"?:"的區(qū)別講解
  • PHP7匿名類(lèi)的用法示例
  • 為Plesk PHP7啟用Oracle OCI8擴(kuò)展方法總結(jié)
  • Centos7.4環(huán)境安裝lamp-php7.0教程
  • PHP7 echo和print語(yǔ)句實(shí)例用法
  • docker自定義鏡像構(gòu)建php7的方法
  • centos7上編譯安裝php7以php-fpm方式連接apache
  • Linux下 php7安裝redis的方法
  • 什么是PHP7中的孤兒進(jìn)程與僵尸進(jìn)程

標(biāo)簽:遵義 荊門(mén) 遂寧 吐魯番 寧夏 徐州 常州 武威

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP7內(nèi)核之Reference詳解》,本文關(guān)鍵詞  PHP7,內(nèi)核,之,Reference,詳解,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《PHP7內(nèi)核之Reference詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于PHP7內(nèi)核之Reference詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    嫩江县| 明水县| 綦江县| 尉犁县| 栾城县| 台北县| 平南县| 光泽县| 杭锦后旗| 青浦区| 顺义区| 阿图什市| 青阳县| 永寿县| 巢湖市| 仪陇县| 阿克| 南陵县| 怀化市| 阜城县| 辽源市| 徐州市| 张家口市| 和平区| 依兰县| 瑞安市| 炎陵县| 察哈| 安塞县| 吴旗县| 中山市| 乐业县| 江山市| 康马县| 平原县| 遵化市| 石棉县| 互助| 特克斯县| 宝清县| 德兴市|