国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何把擴(kuò)展從PHP5升級(jí)到PHP7

AWang / 2914人閱讀

摘要:所以,分配內(nèi)存的宏都被刪掉了。為的輪詢?cè)O(shè)計(jì)了一組宏,使用起來(lái)非常方便。

我在公司的生產(chǎn)環(huán)境已經(jīng)升級(jí)了PHP7,大部分活躍的擴(kuò)展都可以兼容PHP7或者有了PHP7的分支,但是處理protocolbuffers數(shù)據(jù)的擴(kuò)展一直沒(méi)有人來(lái)升級(jí),我只能摸著石頭過(guò)河,自己做一把升級(jí)了。目前已經(jīng)編譯通過(guò),處在處理單測(cè)失敗的case階段,歡迎大家一起討論。對(duì)PHP擴(kuò)展升級(jí)可以先看一下官方的升級(jí)說(shuō)明,https://wiki.php.net/phpng-upgrading,基本可以應(yīng)對(duì)大部分場(chǎng)景,剩下的就需要自己讀源代碼了。

zval

zval結(jié)構(gòu)體是Zend內(nèi)核的非常核心的結(jié)構(gòu),在PHP5和PHP7之間的差別非常大,我給出2處文章供大家學(xué)習(xí),基本上可以代表這塊知識(shí)點(diǎn)最權(quán)威的介紹了。

深入理解PHP7之zval(鳥(niǎo)哥)
https://github.com/laruence/php7-internal/blob/master/zval.md

變量在 PHP7 內(nèi)部的實(shí)現(xiàn)(Nikita Popov)中文版
http://0x1.im/blog/php/Internal-value-representation-in-PHP-7-part-1.html
http://0x1.im/blog/php/Internal-value-representation-in-PHP-7-part-2.html

PHP7不再使用zval的二級(jí)指針,大多數(shù)場(chǎng)景下出現(xiàn)的zval*變量都改成zval,相應(yīng)的使用在這些變量上的宏Z_PP也需要改成Z_P。
在大部分場(chǎng)景下,PHP7是在棧上直接使用zval,不需要去堆上分配內(nèi)存。這時(shí),zval 就需要改成zval,宏也需要從Z__P改成Z_,創(chuàng)建宏從ZVAL_(var)轉(zhuǎn)換成ZVAL_*(&var)。所以,分配zval內(nèi)存的宏

ALLOC_ZVAL、ALLOC_INIT_ZVAL、MAKE_STD_ZVAL都被刪掉了。
-  zval *zv;
-  MAKE_STD_ZVAL(zv);
-  array_init(zv);
+  zval zv;
+  array_init(&zv);

PHP7中zval的long和double類型是不需要引用計(jì)數(shù)的,所以相關(guān)的宏要做調(diào)整。

- Z_ADDREF_P(zv)
+ Z_TRY_ADDREF_P(zv);

PHP7中zval的類型,刪除了IS_BOOL,增加了IS_TRUE和IS_FALSE。

- if (Z_TYPE_P(zv) == IS_BOOL) {
- }
+ if (Z_TYPE_P(zv) == IS_TRUE) {
+ } else if (Z_TYPE_P(zv) == IS_FALSE) {
+ }
zend_string

PHP7中增加了一個(gè)新的內(nèi)置字符串類型zend_string,下面是Zend內(nèi)核中的結(jié)構(gòu)體定義。

struct _zend_string {
    zend_refcounted_h gc;     /* 垃圾回收結(jié)構(gòu)體 */
    zend_ulong        h;      /* 字符串哈希值 */
    size_t            len;    /* 字符串長(zhǎng)度 */
    char              val[1]; /* 字符串內(nèi)容 */
};

gc是PHP7中的所有非標(biāo)量結(jié)構(gòu)都包含的垃圾回收結(jié)構(gòu)體變量;h是字符串哈希值,作為HashTable的key時(shí)不需要每次都重新計(jì)算哈希值,提高了效率;len是字符串長(zhǎng)度,同理每次使用到字符串的長(zhǎng)度時(shí)不需要再計(jì)算,提高了效率;val[1]是C語(yǔ)言的黑科技,此處按照char *理解即可。這里有三個(gè)宏幫助我們方便的使用zend_string的變量。

#define ZSTR_VAL(zstr)  (zstr)->val
#define ZSTR_LEN(zstr)  (zstr)->len
#define ZSTR_H(zstr)    (zstr)->h

創(chuàng)建和銷毀zend_string使用以下方法。

zend_string *zend_string_init(const char *str, size_t len, int persistent)
void zend_string_release(zend_string *s)

zend_string用來(lái)替代PHP5中使用char *和int的場(chǎng)景,尤其是很多API的參數(shù)和返回值都做了調(diào)整。

- int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData)
+ zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)

- void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal);
+ zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal)
HashTable API

在PHP7中使用HashTable的API方法時(shí),有了非常明顯的變化。
查詢方法,PHP5使用引用傳參的方式,同時(shí)返回SUCCESS/FAILURE;PHP7直接返回結(jié)果,查詢無(wú)結(jié)果時(shí)返回NULL。

- int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData)
+ zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)

HashTable的API方法中的key,PHP5中使用char 和int代表的字符串;PHP7中使用zend_string代表的字符串,同時(shí)提供了對(duì)char 和int支持的一組方法,但是需要注意的是這里的字符串長(zhǎng)度是不包括結(jié)尾的"0"的,在升級(jí)擴(kuò)展時(shí)難免會(huì)碰到很多地方需要加減一。

- int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength)
+ zend_bool zend_hash_exists(const HashTable *ht, zend_string *key)
+ zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)

PHP7為HashTable的value為指針時(shí)設(shè)計(jì)了一組API,在常規(guī)的API方法后添加后綴_ptr即可。

void *zend_hash_find_ptr(const HashTable *ht, zend_string *key)
void *zend_hash_update_ptr(HashTable *ht, zend_string *key, void *pData)

PHP7為HashTable的輪詢?cè)O(shè)計(jì)了一組宏,使用起來(lái)非常方便。

ZEND_HASH_FOREACH_VAL(ht, val)
ZEND_HASH_FOREACH_KEY(ht, h, key)
ZEND_HASH_FOREACH_PTR(ht, ptr)
ZEND_HASH_FOREACH_NUM_KEY(ht, h)
ZEND_HASH_FOREACH_STR_KEY(ht, key)
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val)
ZEND_HASH_FOREACH_KEY_VAL(ht, h, key, val)
自定義對(duì)象

這里有點(diǎn)復(fù)雜,我直接附上我的代碼,結(jié)合代碼來(lái)做詳細(xì)說(shuō)明。

typedef struct{
    int max;
    int offset;
    zend_object zo;
} php_protocolbuffers_unknown_field_set;

static zend_object_handlers php_protocolbuffers_unknown_field_set_object_handlers;

static void php_protocolbuffers_unknown_field_set_free_storage(php_protocolbuffers_unknown_field_set *object TSRMLS_DC)
{
    php_protocolbuffers_unknown_field_set *unknown_field_set;
    unknown_field_set = (php_protocolbuffers_unknown_field_set*)((char *) object - XtOffsetOf(php_protocolbuffers_unknown_field_set, zo));

    zend_object_std_dtor(&unknown_field_set->zo TSRMLS_CC);
}
zend_object *php_protocolbuffers_unknown_field_set_new(zend_class_entry *ce TSRMLS_DC)
{
    php_protocolbuffers_unknown_field_set *intern;
    intern = ecalloc(1, sizeof(php_protocolbuffers_unknown_field_set) + zend_object_properties_size(ce));
    zend_object_std_init(&intern->zo, ce);
    object_properties_init(&intern->zo, ce);
    intern->zo.handlers = &php_protocolbuffers_unknown_field_set_object_handlers;
    
    intern->max    = 0; 
    intern->offset = 0;
    
    return &intern->zo;
}
void php_protocolbuffers_unknown_field_set_class(TSRMLS_D)
{
// 此處有省略
    php_protocol_buffers_unknown_field_set_class_entry->create_object = php_protocolbuffers_unknown_field_set_new;
    memcpy(&php_protocolbuffers_unknown_field_set_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    php_protocolbuffers_unknown_field_set_object_handlers.offset = XtOffsetOf(php_protocolbuffers_unknown_field_set, zo);
    php_protocolbuffers_unknown_field_set_object_handlers.free_obj = php_protocolbuffers_unknown_field_set_free_storage;
}

我們想自定義一個(gè)php_protocolbuffers_unknown_field_set的對(duì)象,在它的結(jié)構(gòu)體里面除了zend_object,還有自定義的max和offset,務(wù)必把zend_object放在最后。
實(shí)際生成對(duì)象的地方基本就是標(biāo)準(zhǔn)寫(xiě)法,先分配內(nèi)存,包括php_protocolbuffers_unknown_field_set結(jié)構(gòu)體的內(nèi)存和對(duì)象屬性的內(nèi)存;然后對(duì)zend_object的handlers賦值;最后再對(duì)自己自定義的變量初始化。
實(shí)際生成對(duì)象handler的地方也是標(biāo)準(zhǔn)寫(xiě)法,先分配內(nèi)存,offset是必須設(shè)置的,可選的設(shè)置項(xiàng)有free_obj,dtor_obj,clone_obj。
想取到zend_object,需要(STRUCT_NAME )((char )OBJECT - XtOffsetOf(STRUCT_NAME, zo))

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/21598.html

相關(guān)文章

  • 項(xiàng)目切換PHP7.1.15

    摘要:也可以接入項(xiàng)目打包測(cè)試流程做代碼檢測(cè)。擴(kuò)展替換以后廢棄了和擴(kuò)展,項(xiàng)目中使用的使用的類使用的是已經(jīng)廢棄的擴(kuò)展使用擴(kuò)展做兼容替換。測(cè)試方案和大部分公司差不多,項(xiàng)目組劃分了線下開(kāi)發(fā)環(huán)境預(yù)發(fā)布環(huán)境和生產(chǎn)環(huán)境三個(gè)環(huán)境。 項(xiàng)目由PHP5.5切換至PHP7.1.15 背景 從2015年鳥(niǎo)哥的技術(shù)分享,我們知道PHP7是對(duì)底層實(shí)現(xiàn)得一次完全重構(gòu),函數(shù)調(diào)用機(jī)制和內(nèi)存管理等很多方便做了優(yōu)化,使PHP性能有...

    tuniutech 評(píng)論0 收藏0
  • php7默認(rèn)不安裝bcmath的擴(kuò)展,調(diào)用bcmath函數(shù)會(huì)報(bào)錯(cuò)

    摘要:可以理解為的吧升級(jí)到之后,測(cè)試環(huán)境測(cè)試的時(shí)候發(fā)現(xiàn)直接調(diào)用庫(kù)函數(shù)的地方報(bào)錯(cuò)了。問(wèn)題解決查看了代碼和資料才知道原來(lái)上是默認(rèn)安裝的,而上的默認(rèn)安裝是不安裝的擴(kuò)展的,是會(huì)默認(rèn)支持的,就是可以直接調(diào)用。參考資料官網(wǎng)說(shuō)明其實(shí)是第一條的用戶評(píng)論里面 問(wèn)題描述: ????原本公司使用的是php5.6,然后因?yàn)橐恍┰蛞?jí)到php7,然后代碼中有一些地方使用到了bcmath(就是用來(lái)進(jìn)行任意精度的計(jì)算...

    Ververica 評(píng)論0 收藏0
  • Badoo 告訴你切換 PHP7 節(jié)省了 100 萬(wàn)美元

    摘要:我們?yōu)榱颂幚磉@些挑戰(zhàn),提出了一個(gè)新的引用測(cè)試框架當(dāng)然,也是開(kāi)源的,并且在整個(gè)過(guò)程中節(jié)省了上百萬(wàn)美元。另一方面,被證實(shí)有一些嚴(yán)重的缺點(diǎn)部署困難而且慢。在緩存刷新期間,當(dāng)可用于別的進(jìn)程的已緩存的文件字節(jié)碼在此時(shí)損壞,就會(huì)導(dǎo)致崩潰。 How Badoo saved one million dollars switching to PHP7 我們成功的把我們的應(yīng)用遷移到了php7上面(數(shù)百臺(tái)機(jī)...

    biaoxiaoduan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<