PHP7的FAST_ZPP內(nèi)核用法-創(chuàng)新互聯(lián)

這篇文章主要介紹了PHP7的FAST_ZPP內(nèi)核的使用方法,具有一定借鑒價(jià)值,需要的朋友可以參考下。如下資料是關(guān)于FAST_ZPP的詳細(xì)步驟內(nèi)容。

嶗山網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),嶗山網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為嶗山上1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的嶗山做網(wǎng)站的公司定做!

從PHP7開(kāi)始,大家可能會(huì)發(fā)現(xiàn),不少函數(shù)不再使用傳統(tǒng)的參數(shù)處理方式,而是改用了我們稱(chēng)之為Fast zend parameters parsing(FAST_ZPP)的新型方式, 比如在PHP7之前,count函數(shù)是這樣的:

PHP_FUNCTION(count)
{
    zval *array;
    long mode = COUNT_NORMAL;
 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) {
        return;
    }
    ....
}

在PHP7以后,變成了:

PHP_FUNCTION(count)
{
    zval *array;
    zend_long mode = COUNT_NORMAL;
 
    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_ZVAL(array)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(mode)
    ZEND_PARSE_PARAMETERS_END();
    ...
}

很多PHP擴(kuò)展開(kāi)發(fā)的同學(xué)可能在初次接觸的時(shí)候,會(huì)覺(jué)得很陌生,不要焦慮,讓我慢慢道來(lái) :)

當(dāng)時(shí)在做PHPNG(PHP7的開(kāi)發(fā)項(xiàng)目代號(hào))的開(kāi)發(fā)的時(shí)候,我們主要的發(fā)現(xiàn)性能提升點(diǎn)的一個(gè)方式就是bench各種大型實(shí)際項(xiàng)目,來(lái)發(fā)現(xiàn)占用資源比較大的部分,而最常用benchmark對(duì)象之一是wordpress,因?yàn)樗鼔驈?fù)雜,夠慢,(它也是我們開(kāi)發(fā)JIT的時(shí)候?qū)χ饕猙ench目標(biāo):)) 代表了非OO型代碼類(lèi)的典型應(yīng)用, 在實(shí)際的benchmark的過(guò)程中我們發(fā)現(xiàn),將近有6%的耗時(shí)被zend_parse_parameters給占用了。

事實(shí)上zend_parameters_parsing確實(shí)是一個(gè)很龐大的函數(shù):

ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...)

它根據(jù)type_spec字符串中指定的標(biāo)識(shí)符,來(lái)處理輸入?yún)?shù),而這個(gè)參數(shù)符有很多種(具體含義可以參看: README.PARAMETER_PARSING_API):

a A b C d f h H l L o O p P r s S z * + | / !

根據(jù)不同的組合來(lái)表示我們的PHP函數(shù)要接受的參數(shù)類(lèi)型,比如例子中的count, 通過(guò)”z|l”表示要接受一個(gè)zval類(lèi)型的參數(shù),和一個(gè)可選的long類(lèi)型的mode參數(shù),當(dāng)zend_parse_parameters在runtime的時(shí)候被調(diào)用的時(shí)候,就會(huì)需要分析這些字符,然后調(diào)用對(duì)應(yīng)的邏輯,對(duì)于一些本身就很簡(jiǎn)單的函數(shù)來(lái)說(shuō),比如count,這個(gè)開(kāi)銷(xiāo)就會(huì)顯得很明顯。

再回頭來(lái)看這個(gè)函數(shù)的特點(diǎn),我們會(huì)發(fā)現(xiàn),比如對(duì)于count這個(gè)例子來(lái)說(shuō),其實(shí)type_spec在編譯期就是確定的常量,也就是說(shuō),其實(shí)在編譯的時(shí)候,我們就應(yīng)該已經(jīng)知道了”a|l”應(yīng)該調(diào)用那些對(duì)應(yīng)的參數(shù)處理邏輯。

而事實(shí)上,當(dāng)代的編譯器都具備這個(gè)基本優(yōu)化能力, 比如對(duì)于如下的代碼:

#include <stdlib.h>
 
#define AAA  1;
int main() {
    int a = AAA;
    if (a) {
        abort();
    }
    return 0;
}

如果我們嘗試讓編譯優(yōu)化(-o2)它,并檢查生成的匯編:

main:
.LFB18:
    subq    $8, %rsp
    call    abort@PLT

大家可以看到,if判斷已經(jīng)被抹掉了, 因?yàn)樵诰幾g時(shí)刻, 就能知道a是1, if一定為真。

而FAST_ZPP就是充分借助了這個(gè)能力而來(lái)的一種新型的參數(shù)申明方式, 比如對(duì)于Z_PARAM_ZVAL(array)

#define Z_PARAM_ZVAL_EX(dest, check_null, separate) \
        if (separate) { \
            Z_PARAM_PROLOGUE(separate); \
            zend_parse_arg_zval_deref(_arg, &dest, check_null); \
        } else { \
            ++_i; \
            ZEND_ASSERT(_i <= _min_num_args || _optional==1); \
            ZEND_ASSERT(_i >  _min_num_args || _optional==0); \
            if (_optional && UNEXPECTED(_i >_num_args)) break; \
            _real_arg++; \
            zend_parse_arg_zval(_real_arg, &dest, check_null); \
        }
 
#define Z_PARAM_ZVAL(dest) \
    Z_PARAM_ZVAL_EX(dest, 0, 0)

在編譯時(shí)刻就能被先替換為:

zend_parse_arg_zval(((zval*)execute_data) - 1, &array, 0);

而如果我們進(jìn)一步審視zend_parse_arg_zval:

static zend_always_inline void zend_parse_arg_zval(zval *arg, zval **dest, int check_null)
{
    *dest = (check_null &&
        (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) ||
         (UNEXPECTED(Z_ISREF_P(arg)) &&
          UNEXPECTED(Z_TYPE_P(Z_REFVAL_P(arg)) == IS_NULL)))) ? NULL : arg;
}

我們會(huì)發(fā)現(xiàn)它也是一個(gè)inline申明的函數(shù),而參數(shù)因?yàn)槭浅A浚敲淳涂梢赃M(jìn)一步被evaluate成:

zval *array = ((zval*)execute_data) - 1;

怎么樣,是不是一看就知道會(huì)快很多? 沒(méi)有type_spec分析,沒(méi)有額外的函數(shù)調(diào)用,直接獲取到參數(shù)。

剛剛說(shuō)到的inline函數(shù)可以在編譯時(shí)期根據(jù)常數(shù)的剪枝內(nèi)聯(lián), 也是用來(lái)避免同類(lèi)函數(shù)的重復(fù)代碼的很好的方法,在PHP7中也有大量使用,有興趣的可以參看zend_hash.c中的很多相似函數(shù)的定義。

當(dāng)然,這么做也有一個(gè)問(wèn)題就是, 會(huì)增大我們程序的binary size, 這個(gè)也很容易理解, 比如對(duì)于count來(lái)說(shuō),本來(lái)原來(lái)只是調(diào)用一個(gè)外部函數(shù),一個(gè)call指令就夠了,但現(xiàn)在就會(huì)有很多內(nèi)聯(lián)進(jìn)來(lái)的指令。

而binary size變大以后,執(zhí)行時(shí)期的cache miss就會(huì)增大,也會(huì)影響性能,所以FAST_ZPP我們也不是建議全部使用, 而真是針對(duì)實(shí)際應(yīng)用中調(diào)用頻率比較大,并且本身函數(shù)邏輯較為簡(jiǎn)單的函數(shù)來(lái)使用.

總結(jié)一下,一般來(lái)說(shuō),我們自己寫(xiě)的擴(kuò)展函數(shù),并不需要一定使用FAST_ZPP, 因?yàn)槿绻陨硎菑?fù)雜的函數(shù)邏輯的, 這點(diǎn)開(kāi)銷(xiāo)對(duì)比起來(lái),其實(shí)也還好了。

最后,附上新的FAST_ZPP API和老的參數(shù)描述之間的對(duì)應(yīng)如下:

PHP7的FAST_ZPP內(nèi)核用法

以上就是PHP7的FAST_ZPP內(nèi)核的詳細(xì)內(nèi)容了,看完之后是否有所收獲呢?如果想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。

名稱(chēng)欄目:PHP7的FAST_ZPP內(nèi)核用法-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://bm7419.com/article22/dseecc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、電子商務(wù)、網(wǎng)站維護(hù)、企業(yè)網(wǎng)站制作網(wǎng)站制作、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司