前面我們討論了內(nèi)存的工作原理,也進(jìn)行了一些性能相關(guān)的測試。那么今天開始我們來看幾個在實踐中的應(yīng)用。首先我們先從PHP開始。2015年,PHP7的發(fā)布可以說是在技術(shù)圈里引起了不小的轟動,因為它的執(zhí)行效率比PHP5直接翻了一倍。PHP7在內(nèi)存方面,你是否知道作者都進(jìn)行了哪些優(yōu)化?幾個核心結(jié)構(gòu)體的改進(jìn)只是表面上看起來優(yōu)化的幾個字節(jié)那么簡單?讓我們從幾個核心的數(shù)據(jù)結(jié)構(gòu)改進(jìn)開始看起。
1 PHP7zval的變化
1、php5.3中的zval:
我們這里只討論64位操作系統(tǒng)下的情況。該zval_struct結(jié)構(gòu)體中的由四個成員構(gòu)成,其中zvalue_value稍微復(fù)雜一些,是一個聯(lián)合體。聯(lián)合體中最長的成員是一個指針加一個int,8+4=12字節(jié)。但是默認(rèn)情況下,會進(jìn)行內(nèi)存對齊,故zval_struct會占用16字節(jié)。那么。
_zval_struct總的字節(jié) = value(16)+ refcount__gc(4)+ type(1)+ is_ref__gc(1)= 占用22字節(jié)。
最后再考慮下內(nèi)存對齊,實際占用24字節(jié)。(如果算的有點(diǎn)暈話,感興趣的同學(xué)可以寫段簡單的測試代碼,使用sizeof查看一下)
2、PHP7.2中的zval
7.2中的zval_struct結(jié)構(gòu)體里由3個成員構(gòu)成,其中zend_value看起來比較復(fù)雜,實際上只是一個8字節(jié)的聯(lián)合體。u1也是一個聯(lián)合體,占用是4個字節(jié)。u2也一樣。這樣zval_struct就實際占用16個字節(jié)。
2 PHP7 HashTable的變化
1、PHP5.3里的HashTable:
在5.3里HashTable就是一個大struct, 有點(diǎn)小復(fù)雜,我們拆開了細(xì)說,
uint nTableSize 4字節(jié)
uint nTableMask 4字節(jié)
uint nNumOfElements 4字節(jié),
ulong nNextFreeElement 8字節(jié) 注意這前面的4個字節(jié)會被浪費(fèi)掉,因為nNextFreeElement的開始地址需要對齊
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前面這四個字節(jié)會留空)+8+8+8+8+8+8+1+1+1 = 67字節(jié)。再加上結(jié)構(gòu)體本身要對齊到8的整數(shù)倍,所以實際占用72字節(jié)。
2、PHP7.2里的HashTable:
在7.2里HashTable
zend_refcounted_h gc 看起來唬人,實際就是個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)存對齊的狀態(tài),沒有額外的浪費(fèi)。
另外還有PHP源代碼里經(jīng)常出鏡的Buckets也從72下降到了32字節(jié),這里我就不翻源代碼了。
3 優(yōu)化思想精髓
當(dāng)當(dāng)當(dāng),敲黑板,重點(diǎn)來了!我們看了兩個核心數(shù)據(jù)結(jié)構(gòu)的結(jié)構(gòu)體變化,這上面的優(yōu)化都是什么含義呢?拿HashTable舉例,貌似從72字節(jié)優(yōu)化到了56字節(jié),這內(nèi)存節(jié)約的也不是特別多嘛,才20%多而已!但這中間其實隱藏了兩個較深層次優(yōu)化思路:
第一、你是否記得我們前面CPU在向內(nèi)存要數(shù)據(jù)的時候是以Cache Line為單位進(jìn)行的,而我們說過Cache Line的大小就是64字節(jié)。回過頭來看HashTable,在7.2里的56字節(jié),只需要CPU向內(nèi)存進(jìn)行一次Cache Line大小的burst IO,就夠了。而在5.3里的72字節(jié),雖然只比Cache Line大了那么一丟丟,但是對不起,必須得進(jìn)行兩次burst IO才可以。所以,在計算機(jī)里,56字節(jié)相對72字節(jié)實際上是翻倍的性能提升!!
第二、CPU的L1、L2、L3的容量是固定的幾十K或者幾十M。假設(shè)Cache的都是HashTable,那么Cache容量不變的條件下,能Cache住的HashTable將會翻倍,緩存命中率提升一大截。要知道L1命中后只需要1ns多一點(diǎn)的耗時,而如果穿透到內(nèi)存的話可能就需要40多納秒的延時了,整整差了幾十倍。
所以PHP內(nèi)核的作者大牛深諳CPU與內(nèi)存的工作原理,表面上看起來只是幾個字節(jié)的節(jié)約,但是實際上爆發(fā)出了巨大的性能提升!!
審核編輯:劉清
-
cpu
+關(guān)注
關(guān)注
68文章
11080瀏覽量
217155 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3125瀏覽量
75281 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
7152瀏覽量
125632 -
PHP
+關(guān)注
關(guān)注
0文章
454瀏覽量
27556
發(fā)布評論請先 登錄
TPS62684 1600mA 高效降壓轉(zhuǎn)換器,針對小尺寸解決方案進(jìn)行了優(yōu)化數(shù)據(jù)手冊

HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問題性能優(yōu)化四
HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問題性能優(yōu)化一
SOLIDWORKS?2025在電氣設(shè)計與仿真方面進(jìn)行了優(yōu)化

iMX8MPlus SoC M7核心是否需要單獨(dú)的RAM內(nèi)存?
使用ADS1198-FE下載了軟件按照說明進(jìn)行了調(diào)試,出現(xiàn)了兩個問題求解決
hyper 內(nèi)存,Hyper內(nèi)存:如何監(jiān)控與優(yōu)化hyper-v虛擬機(jī)的內(nèi)存使用

高壓SiC針對電動汽車長途卡車運(yùn)輸中的兆瓦級充電進(jìn)行了優(yōu)化

FPGA通過SPI對DAC進(jìn)行了配置,用頻譜儀測不到輸出是怎么回事?
SOLIDWORKS 2025界面布局的優(yōu)化
新內(nèi)存藍(lán)屏死機(jī)?內(nèi)存驗貨指南你值得擁有

如何優(yōu)化RAM內(nèi)存使用
這些電源常用仿真軟件,你都知道嗎?
TLV320AIC3106IRGZT隨著PGA音量的抬高是不是同時將底噪也進(jìn)行了放大?
石墨烯基導(dǎo)電油墨具有良好的滲透性和低阻抗,針對 RFID天線性能進(jìn)行了優(yōu)

評論