0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

PHP7在內(nèi)存方面你是否知道都進(jìn)行了哪些優(yōu)化

冬至配餃子 ? 來(lái)源:開(kāi)發(fā)內(nèi)功修煉 ? 作者:張彥飛allen ? 2022-08-30 17:08 ? 次閱讀

前面我們討論了內(nèi)存的工作原理,也進(jìn)行了一些性能相關(guān)的測(cè)試。那么今天開(kāi)始我們來(lái)看幾個(gè)在實(shí)踐中的應(yīng)用。首先我們先從PHP開(kāi)始。2015年,PHP7的發(fā)布可以說(shuō)是在技術(shù)圈里引起了不小的轟動(dòng),因?yàn)樗膱?zhí)行效率比PHP5直接翻了一倍。PHP7在內(nèi)存方面,你是否知道作者都進(jìn)行了哪些優(yōu)化?幾個(gè)核心結(jié)構(gòu)體的改進(jìn)只是表面上看起來(lái)優(yōu)化的幾個(gè)字節(jié)那么簡(jiǎn)單?讓我們從幾個(gè)核心的數(shù)據(jù)結(jié)構(gòu)改進(jìn)開(kāi)始看起。

1 PHP7zval的變化

1、php5.3中的zval:

pYYBAGMN0taADI7ZAACph_e53O8634.png

我們這里只討論64位操作系統(tǒng)下的情況。該zval_struct結(jié)構(gòu)體中的由四個(gè)成員構(gòu)成,其中zvalue_value稍微復(fù)雜一些,是一個(gè)聯(lián)合體。聯(lián)合體中最長(zhǎng)的成員是一個(gè)指針加一個(gè)int,8+4=12字節(jié)。但是默認(rèn)情況下,會(huì)進(jìn)行內(nèi)存對(duì)齊,故zval_struct會(huì)占用16字節(jié)。那么。

_zval_struct總的字節(jié) = value(16)+ refcount__gc(4)+ type(1)+ is_ref__gc(1)= 占用22字節(jié)。

最后再考慮下內(nèi)存對(duì)齊,實(shí)際占用24字節(jié)。(如果算的有點(diǎn)暈話(huà),感興趣的同學(xué)可以寫(xiě)段簡(jiǎn)單的測(cè)試代碼,使用sizeof查看一下)

2、PHP7.2中的zval

poYBAGMN0uyAUol1AADs2EZskZs450.png

7.2中的zval_struct結(jié)構(gòu)體里由3個(gè)成員構(gòu)成,其中zend_value看起來(lái)比較復(fù)雜,實(shí)際上只是一個(gè)8字節(jié)的聯(lián)合體。u1也是一個(gè)聯(lián)合體,占用是4個(gè)字節(jié)。u2也一樣。這樣zval_struct就實(shí)際占用16個(gè)字節(jié)。

2 PHP7 HashTable的變化

1、PHP5.3里的HashTable:

pYYBAGMN0v-AGU2NAACNlGKBu8M639.png

在5.3里HashTable就是一個(gè)大struct, 有點(diǎn)小復(fù)雜,我們拆開(kāi)了細(xì)說(shuō),

uint nTableSize 4字節(jié)

uint nTableMask 4字節(jié)

uint nNumOfElements 4字節(jié),

ulong nNextFreeElement 8字節(jié) 注意這前面的4個(gè)字節(jié)會(huì)被浪費(fèi)掉,因?yàn)閚NextFreeElement的開(kāi)始地址需要對(duì)齊

Bucket *pInternalPointer 8字節(jié)

Bucket *pListHead 8字節(jié)

Bucket *pListTail 8字節(jié)

Bucket **arBuckets 8字節(jié)

dtor_func_t pDestructor 8字節(jié)

zend_bool persistent 1字節(jié)

unsigned char nApplyCoun 1字節(jié)

zend_bool bApplyProtection 1字節(jié)

最終,總字節(jié)數(shù) = 4+4+4+4(nNextFreeElement前面這四個(gè)字節(jié)會(huì)留空)+8+8+8+8+8+8+1+1+1 = 67字節(jié)。再加上結(jié)構(gòu)體本身要對(duì)齊到8的整數(shù)倍,所以實(shí)際占用72字節(jié)。

2、PHP7.2里的HashTable:

pYYBAGMN0xKAQDrkAACWEr2NQKE768.png

在7.2里HashTable

zend_refcounted_h gc 看起來(lái)唬人,實(shí)際就是個(gè)long,占用8字節(jié)

union... u 占用4字節(jié)

uint32_t 占用4字節(jié)

Bucket* 指針占用8字節(jié)

uint32_t nNumUsed 占用4字節(jié)

uint32_t nNumOfElements 占用4字節(jié)

uint32_t nTableSize 占用4字節(jié)

uint32_t nInternalPointer 占用4字節(jié)

zend_long nNextFreeElement 占用8字節(jié)

dtor_func_t pDestructor 占用8字節(jié)

總占用

字節(jié)數(shù) = 8+4+4+8+4+4+4+4+8+8 = 56字節(jié),并且正好達(dá)到了內(nèi)存對(duì)齊的狀態(tài),沒(méi)有額外的浪費(fèi)。

另外還有PHP源代碼里經(jīng)常出鏡的Buckets也從72下降到了32字節(jié),這里我就不翻源代碼了。

3 優(yōu)化思想精髓

當(dāng)當(dāng)當(dāng),敲黑板,重點(diǎn)來(lái)了!我們看了兩個(gè)核心數(shù)據(jù)結(jié)構(gòu)的結(jié)構(gòu)體變化,這上面的優(yōu)化都是什么含義呢?拿HashTable舉例,貌似從72字節(jié)優(yōu)化到了56字節(jié),這內(nèi)存節(jié)約的也不是特別多嘛,才20%多而已!但這中間其實(shí)隱藏了兩個(gè)較深層次優(yōu)化思路:

第一、你是否記得我們前面CPU在向內(nèi)存要數(shù)據(jù)的時(shí)候是以Cache Line為單位進(jìn)行的,而我們說(shuō)過(guò)Cache Line的大小就是64字節(jié)?;剡^(guò)頭來(lái)看HashTable,在7.2里的56字節(jié),只需要CPU向內(nèi)存進(jìn)行一次Cache Line大小的burst IO,就夠了。而在5.3里的72字節(jié),雖然只比Cache Line大了那么一丟丟,但是對(duì)不起,必須得進(jìn)行兩次burst IO才可以。所以,在計(jì)算機(jī)里,56字節(jié)相對(duì)72字節(jié)實(shí)際上是翻倍的性能提升??!

第二、CPU的L1、L2、L3的容量是固定的幾十K或者幾十M。假設(shè)Cache的都是HashTable,那么Cache容量不變的條件下,能Cache住的HashTable將會(huì)翻倍,緩存命中率提升一大截。要知道L1命中后只需要1ns多一點(diǎn)的耗時(shí),而如果穿透到內(nèi)存的話(huà)可能就需要40多納秒的延時(shí)了,整整差了幾十倍。

所以PHP內(nèi)核的作者大牛深諳CPU與內(nèi)存的工作原理,表面上看起來(lái)只是幾個(gè)字節(jié)的節(jié)約,但是實(shí)際上爆發(fā)出了巨大的性能提升??!



審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10807

    瀏覽量

    210852
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2978

    瀏覽量

    73817
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6689

    瀏覽量

    123142
  • PHP
    PHP
    +關(guān)注

    關(guān)注

    0

    文章

    452

    瀏覽量

    26630
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何優(yōu)化RAM內(nèi)存使用

    :使用任務(wù)管理器查看當(dāng)前運(yùn)行的程序和服務(wù),關(guān)閉那些不需要的。 禁用啟動(dòng)程序 :減少開(kāi)機(jī)啟動(dòng)項(xiàng),只保留必要的程序。 2. 優(yōu)化操作系統(tǒng)設(shè)置 調(diào)整虛擬內(nèi)存 :合理設(shè)置虛擬內(nèi)存,避免過(guò)多占用硬盤(pán)空間。 清理磁盤(pán) :定期
    的頭像 發(fā)表于 11-11 09:58 ?44次閱讀

    這些電源常用仿真軟件,知道嗎?

    諧振變換器電路進(jìn)行了仿真建模,感興趣的工程師們可以去回顧一下,這里就不贅述了。 常用仿真軟件 在進(jìn)行電源設(shè)備設(shè)計(jì)仿真時(shí),會(huì)涉及到電路、電磁、熱學(xué)、力學(xué)方面的仿真。 電路仿真: 通過(guò)仿真軟件將電路的元件
    發(fā)表于 10-25 14:20

    ESP32S3的EEPROM是由FLASH虛擬的,直接在arduinoIDE中擦寫(xiě)EEPROM時(shí)是否在底層自動(dòng)進(jìn)行了磨損平衡?

    ESP32S3的EEPROM是由FLASH虛擬的,請(qǐng)問(wèn)直接在arduinoIDE中擦寫(xiě)EEPROM時(shí)是否在底層自動(dòng)進(jìn)行了磨損平衡? 在用ESP32S3做含有計(jì)數(shù)器功能的設(shè)備,希望可以掉電保存數(shù)據(jù)
    發(fā)表于 06-07 06:27

    是否真的了解結(jié)構(gòu)體占用了多少字節(jié)?

    結(jié)構(gòu)體成員所占內(nèi)存空間大小一般情況下,如果想知道結(jié)構(gòu)體成員的內(nèi)存占用情況需要:1、先用結(jié)構(gòu)體在內(nèi)存中開(kāi)空間2、使用sizeof(結(jié)構(gòu)體變量.成員名)或者sizeof(結(jié)構(gòu)體指針->成員
    的頭像 發(fā)表于 06-04 08:04 ?362次閱讀
    <b class='flag-5'>你</b><b class='flag-5'>是否</b>真的了解結(jié)構(gòu)體占用了多少字節(jié)?

    針對(duì)功率密度和低EMI進(jìn)行了優(yōu)化的LM62460、LM61480和LM61495引腳兼容6A/8A/10A降壓轉(zhuǎn)換器數(shù)據(jù)表

    電子發(fā)燒友網(wǎng)站提供《針對(duì)功率密度和低EMI進(jìn)行了優(yōu)化的LM62460、LM61480和LM61495引腳兼容6A/8A/10A降壓轉(zhuǎn)換器數(shù)據(jù)表.pdf》資料免費(fèi)下載
    發(fā)表于 04-11 09:55 ?0次下載
    針對(duì)功率密度和低EMI<b class='flag-5'>進(jìn)行了</b><b class='flag-5'>優(yōu)化</b>的LM62460、LM61480和LM61495引腳兼容6A/8A/10A降壓轉(zhuǎn)換器數(shù)據(jù)表

    什么是HBM3E內(nèi)存?Rambus HBM3E/3內(nèi)存控制器內(nèi)核

    Rambus HBM3E/3 內(nèi)存控制器內(nèi)核針對(duì)高帶寬和低延遲進(jìn)行了優(yōu)化,以緊湊的外形和高能效的封裝為人工智能訓(xùn)練提供了最大的性能和靈活性。
    發(fā)表于 03-20 14:12 ?2210次閱讀
    什么是HBM3E<b class='flag-5'>內(nèi)存</b>?Rambus HBM3E/3<b class='flag-5'>內(nèi)存</b>控制器內(nèi)核

    使用STM32H7的AD進(jìn)行了7M頻率的采集信號(hào),采集進(jìn)去后可以實(shí)現(xiàn)實(shí)時(shí)處理嗎?

    使用STM32H7的AD進(jìn)行了7M頻率的采集信號(hào),采集進(jìn)去后可以實(shí)現(xiàn)實(shí)時(shí)處理嗎?
    發(fā)表于 03-08 08:10

    數(shù)組和鏈表在內(nèi)存中的區(qū)別 數(shù)組和鏈表的優(yōu)缺點(diǎn)

    數(shù)組和鏈表在內(nèi)存中的區(qū)別 數(shù)組和鏈表的優(yōu)缺點(diǎn)? 數(shù)組和鏈表是常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),用于組織和存儲(chǔ)數(shù)據(jù)。它們在內(nèi)存中的存儲(chǔ)方式以及優(yōu)缺點(diǎn)方面存在一些顯著的差異。本文將詳細(xì)探討這些差異以及它們的優(yōu)缺點(diǎn)。 1.
    的頭像 發(fā)表于 02-21 11:30 ?859次閱讀

    軟件測(cè)試的7大原則,漏了幾條?

    of error-fallacy) 99%無(wú)錯(cuò)誤的軟件仍然可能無(wú)法使用,如果針對(duì)缺陷要求對(duì)系統(tǒng)進(jìn)行了全面測(cè)試,則可能是這種情況。軟件測(cè)試不僅僅是為了發(fā)現(xiàn)缺陷,而且還要檢查軟件是否滿(mǎn)足業(yè)務(wù)需求。沒(méi)有錯(cuò)誤是謬論,即如
    發(fā)表于 01-18 09:39

    知道無(wú)人機(jī)性能是否優(yōu)異,看這3個(gè)參數(shù)

    拿縱橫最新發(fā)布的CW-007大鵬來(lái)說(shuō)。飛機(jī)的外形擁有完全的自主知識(shí)產(chǎn)權(quán)。在外形設(shè)計(jì)方面使用了CFD數(shù)值優(yōu)化技術(shù),對(duì)機(jī)翼的翼型分布和翼尖的上翹延伸小翼進(jìn)行了優(yōu)化,最大限度地提高升阻比,保
    的頭像 發(fā)表于 12-10 11:56 ?2048次閱讀
    想<b class='flag-5'>知道</b>無(wú)人機(jī)性能<b class='flag-5'>是否</b>優(yōu)異,看這3個(gè)參數(shù)

    肖特基二極管4大特性,知道嗎?

    肖特基二極管4大特性,知道嗎?
    的頭像 發(fā)表于 12-07 16:29 ?665次閱讀
    肖特基二極管4大特性,<b class='flag-5'>你</b><b class='flag-5'>都</b><b class='flag-5'>知道</b>嗎?

    php的mysql無(wú)法啟動(dòng)

    ,以便幫助讀者快速解決相關(guān)問(wèn)題。 一、安裝環(huán)境配置檢查 1.1 PHP版本檢查 在使用PHP連接MySQL之前,首先要確保PHP版本的兼容性。查看所使用的PHP版本
    的頭像 發(fā)表于 12-04 15:59 ?1361次閱讀

    php是前端還是后端

    ,我們將詳細(xì)介紹PHP的各個(gè)方面,包括其特點(diǎn)、歷史、用途、優(yōu)點(diǎn)和缺點(diǎn)等。 首先,讓我們來(lái)了解一下PHP的背景和歷史。PHP最早由Rasmus Lerdorf于1994年開(kāi)發(fā),并命名為“
    的頭像 發(fā)表于 12-04 15:46 ?2179次閱讀

    php運(yùn)行環(huán)境的配置步驟

    從官方網(wǎng)站(http://php.net/downloads.php)下載PHP的安裝包。根據(jù)操作系統(tǒng)的不同,選擇對(duì)應(yīng)的安裝包進(jìn)行下載。如果
    的頭像 發(fā)表于 12-04 15:27 ?1095次閱讀

    php運(yùn)行環(huán)境本地測(cè)試地址是

    PHP運(yùn)行環(huán)境本地測(cè)試地址是指在本地計(jì)算機(jī)上搭建的用于測(cè)試和運(yùn)行PHP代碼的的環(huán)境地址。搭建該運(yùn)行環(huán)境可以方便開(kāi)發(fā)人員在本地進(jìn)行開(kāi)發(fā)、調(diào)試和測(cè)試工作,以提高開(kāi)發(fā)效率和優(yōu)化代碼質(zhì)量。本文
    的頭像 發(fā)表于 12-04 15:25 ?664次閱讀