日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

PHP7的变化

發(fā)布時間:2023/12/15 php 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP7的变化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

引言

PHP7與PHP5版本相比有非常大的變化,尤其是在Zend引擎方面。為了提升性能,PHP7對Zend進(jìn)行了深度優(yōu)化,使得PHP的運行速度大大提高,比PHP5.0-5.6快了近5倍,同時還降低了PHP對系統(tǒng)資源的占用。

PHP7比較大的變化有:

抽象語法樹

PHP是一種解釋性語言,通過解析器來執(zhí)行。

那么首先來看一下編譯器與解釋器的區(qū)別:讀入源語言后,解釋器和編譯器都要進(jìn)行詞法分析、語法分析和語義分析,之后,二者開始有所分別。

  • 解析器與編譯器的區(qū)別:

    • 解釋器在語義分析后選擇了直接執(zhí)行語句;
    • 編譯器在語義分析后選擇將將語義存儲成某一種中間語言,之后通過不同的后端翻譯成不同的機器語言(可執(zhí)行程序)。其存在一個預(yù)編譯的過程。如下圖所示:

  • PHP7之前的版本,代碼解釋過程:

    • PHP代碼在語法解析階段直接生成ZendVM指令,即在zend_language_parser.y中直接生成opline指令,使得編譯器與執(zhí)行器耦合在一起。
    • 編譯生成的指令再供執(zhí)行引擎使用,該指令是在語法指令直接生成的,若要更換執(zhí)行引擎,怎需要修改語法解析規(guī)則;若PHP語法變化,但沒有修改執(zhí)行引擎,仍需要修改語法解析規(guī)則。其代碼解析過程如下圖:

  • PHP7的代碼解析過程:

Native TLS

PHP5.x版本擴展中,有TSRM_CC、TSRM_DC宏,用于線程安全。

PHP中有很多變量需要在不同函數(shù)間共享,多線程的環(huán)境下不能簡單地通過全局變量來實現(xiàn),為了適應(yīng)線程的應(yīng)用環(huán)境,PHP提供了一個線程安全資源管理器,將全局資源進(jìn)行線程隔離,不同的線程之間互不干擾。

使用全局資源需要先獲取本線程的資源池,這個過程比較占用時間,因此,PHP5.x通過參數(shù)傳遞的方式將本線程的資源池傳遞給其他函數(shù),避免重復(fù)查找。這種方式需要所有函數(shù)接受資源池的參數(shù)(TSRM_DC宏所加的參數(shù)),這些參數(shù)傳遞不僅易遺漏參數(shù),還是得代碼不優(yōu)雅

PHP7使用Native TLS(線程局部存儲)來保存線程的資源池,簡單來說就是通過__thread標(biāo)識一個全局變量,這樣這個全局變量就是線程獨享的了,不同線程的修改不會相互影響。

指定函數(shù)參數(shù)、返回值類型

輸入和輸出參數(shù)必須是指定的數(shù)據(jù)類型,示例如下:

1
2
3
function foo(string $name): array {
return [];
}

zval結(jié)構(gòu)的變化

Zval是PHP中最重要的數(shù)據(jù)結(jié)構(gòu)之一(另一個比較重要的數(shù)據(jù)結(jié)構(gòu)是hash table),它包含了PHP中的變量值和類型的相關(guān)信息。它是一個struct,在PHP5.x中,基本結(jié)構(gòu)為:

1
2
3
4
5
6
7
struct _zval_struct {
zvalue_value value; /* value,變量的具體值 */
zend_uint refcount__gc; /* variable ref count,記錄變量的引用計數(shù)(自動回收的基礎(chǔ)) */
zend_uchar type; /* active type ,類型*/
zend_uchar is_ref__gc; /* if it is a ref variable,標(biāo)識變量是否為引用 */
};
typedef struct _zval_struct zval;

變量的實際值,具體來說是一個zvalue_value的聯(lián)合體(union),用來適配不同的變量類型:

1
2
3
4
5
6
7
8
9
10
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct { /* string */
char *val;
int len;
} str;
HashTable *ht; /* hash table value,used for array */
zend_object_value obj; /* object */
} zvalue_value;

參考:PHP內(nèi)核探索之變量(1)變量的容器-Zval

PHP5.x中引用計數(shù)是在zval中,而不是在具體的value中,這樣一來,導(dǎo)致變量復(fù)制時需要復(fù)制兩個結(jié)構(gòu),zval,zvalue_value始終是綁定在一起的。

  • 變化1:PHP7中將引用計數(shù)轉(zhuǎn)移到具體的value中,這樣更合理,因為zval只是變量的一個載體,可以簡單地認(rèn)為是變量名,而value才是真正的值,這個改變使得PHP變量之間的復(fù)制、傳遞更加簡潔、易懂
  • 變化2:zval結(jié)構(gòu)的大小由24byte減少到16byte,這PHP7能夠降低系統(tǒng)的資源占用。

異常處理

PHP5.x中很多操作會直接拋出error錯誤,PHP7中將多數(shù)錯誤改為了異常拋出,這樣就可以通過try catch捕捉到異常。這種新的異常處理方式使得錯誤處理更加可控。

HashTable的變化

HashTable,即哈希表,也稱為散列表,它是PHP強大的array()類型的內(nèi)部實現(xiàn)結(jié)構(gòu),也是內(nèi)核中使用非常頻繁的一個結(jié)構(gòu),函數(shù)符號表、類符號表、常量符號表等都是通過HashTable實現(xiàn)的。

PHP7中,HashTable結(jié)構(gòu)的大小由72byte減小到56byte,同時,數(shù)組元素Bucket結(jié)構(gòu)也由72byte減小到32byte。

執(zhí)行器

execute_data、opline采用寄存器變量存儲,執(zhí)行器的調(diào)度函數(shù)為execute_ex(),這個函數(shù)復(fù)制執(zhí)行PHP代碼編譯生成ZendVM指令。在執(zhí)行期間會頻繁地用到execute_data、opline兩個變量。

PHP5.x中,這兩個變量是由execute_ex()通過參數(shù)傳遞給各指令handle的。

PHP7中不再采用傳參的方式,而是將execute_data、opline通過寄存器來存儲,避免傳參導(dǎo)致的頻繁出入棧操作,同時寄存器相比于內(nèi)存的訪問速度更快。這個優(yōu)化使得PHP的性能有了5%左右的提升。

新的參數(shù)解析

PHP5.x通過zend_parse_parameters()解析函數(shù)的參數(shù),PHP7提供另外一種方式,同時保留原來方式,但是新的解析方式速度更快。

參考:秦朋 《PHP7內(nèi)核剖析》第1.3節(jié)

推薦文章——關(guān)于PHP內(nèi)部實現(xiàn)的文章:

  • 給PHP開發(fā)者的PHP源碼(1):源碼結(jié)構(gòu)
  • 理解 PHP 內(nèi)部函數(shù)的定義
  • PHP 的變量實現(xiàn)
  • 理解數(shù)組在PHP內(nèi)部的實現(xiàn)
  • 總結(jié)

    以上是生活随笔為你收集整理的PHP7的变化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。