PHP陣列記憶體利用率低和弱型別詳細解讀

2022-10-06 08:03:12 字數 2447 閱讀 5302

這兩天任務提前完成,可以喘口氣沉澱一下,深入學習學習php。其實本來是想了解一下php效能優化相關的東西,但被網上的一句「php陣列記憶體利用率低,c語言100mb的記憶體陣列,php裡需要1g」驚到了。php真的這麼耗記憶體麼?於是藉此機會了解了php的資料型別實現方式。

先來做個測試:

<?php echo memory_get_usage() , '

'; $start = memory_get_usage();

$a = array();

for ($i=0; $i<1000; $i++)

$end = memory_get_usage();

echo memory_get_usage() , '

'; echo 'ar**:', ($end - $start)/1000 ,'bytes' , '

';所得結果:

353352

437848

ar**:84.416bytes

1000個元素的整數陣列耗費記憶體(437848 - 353352)位元組,約合82kb,也就是說每個元素所佔記憶體84位元組。在c語言中,乙個int佔位是4位元組,整體相差了20倍。

但是網上又說memery_get_usage()返回的結果不全是陣列占用,還包括php本身的一些結構,因此,換種方式,採用php內建函式生成陣列試試:

<?php $start = memory_get_usage();

$a = array_fill(0, 10程式設計客棧000, 1);

$end = memory_get_usage(); //10k elements array;

echo 'ar**:', ($end - $start )/10000,'byte' , '

';輸出為:

ar**:54.5792byte

比剛才略好,但也54位元組,確實差了10倍左右。

究其原因,還得從php的底層實現說起。php是一種弱型別的語言,不分int,double,string之類的,統一乙個'$'就能解決所有問題。php底層由c語言實現,每個變數都對應乙個zval結構,其詳細定義為:

typedef struct _zval_struct zval;

struct _zval_struct ;

php使用union結構來儲存變數的值,zval中zvalue_value型別的value變數即為乙個union,定義如下:

typedef union _zvalue_value str;

hashtable *ht; /* hash table value */

zend_object_value obj; /*object value */

} zvalue_value;

union型別占用記憶體的大小有其最大的成員所佔的資料空間決定。在zvalue_value中,str結構體的int佔4位元組,char指標佔4位元組,故整個zvalue_value所佔記憶體為8位元組。

zval的大小即為8 + 4 + 1 + 1 = 14位元組。

注意到zvalue_value中還有乙個hashtable是做什麼的?zval中,陣列、字串和物件還需要另外的儲存結構,陣列的儲存結構即為hashtable。

hashtable定義給出:

typedef struct _hashtable hashtable;

除了幾個記錄table大小,所含元素數量的屬性變數外,bucket被多次使用到,bucket是如何定義的:

typedef struct bucket bucket;

有點像乙個鍊錶,bucket就像是乙個鍊錶節點,有具體的資料和指標,而hashtable就是乙個array,儲存著一串bucket元素。php中多維陣列的實現,不過就是bucket裡面存著另乙個hashtable罷了。

算一算hashtable需要占用39個位元組,bucket需要33個位元組。乙個空的陣列就需要占用14 + 39 + 33 = 86個位元組。bucket 結構需要 33 個位元組,鍵長超過四個位元組的部分附加在 bucket 後面,而元素值很可能是乙個 zval 結構,另外每個陣列會分配乙個由 arbuckets 指向的 bucket 指標陣列, 雖然不能說每增加乙個元素就需要乙個指標,但是實際情況可能更糟。這麼算來乙個陣列元素就會占用 54 個位元組,與上面的估算幾乎一樣。

從空間的角度來看,小型陣列平均代價較大,當然乙個指令碼中不會充斥數量很大的小型陣列,可以以較小的空間代價來獲取程式設計上的快捷。但如果將陣列當作容器來使用就是另一番景象了,實際應用經常會遇到多維陣列,而且元素居多。比如10k個元素的一維陣列大概消耗540k記憶體,而10k x 10 的二維陣列理論上只需要 6m 左右的空間,但是按照 memory_get_usage 的結果則兩倍於此,[10k,5,2]的三維陣列居然消耗了23m,小型陣列確實是划不來的。

php陣列記憶體利用率低的原因,講到這裡,接下來的文章將解讀php陣列操作的具體實現。

本文標題: php陣列記憶體利用率低和弱型別詳細解讀

本文位址:

記憶體利用率

記憶體利用率 有多個命令提供有關系統記憶體利用率的相關資訊。最流行的是free 和pmap。free命令 free 命令顯示可用的物理記憶體量,其中包括總物理記憶體量 已用物理記憶體量 可用物理記憶體量。它也為交換空間顯示同樣的統計資訊,還顯示核心使用的記憶體快取大小和緩衝區的大小。圖7 5 顯示了...

HashMap的記憶體利用率

有規律的整數 字串 test public void testhashsize 這個時候往往不會構建鍊錶和紅黑色。而是底層真的是陣列。無規律的key test public void testhashsize 記憶體中陣列長度,元素個數。使用下面的 看看talbe中有多少不為空 int a 0 fo...

linux查詢記憶體真是利用率

使用top工具檢視到suse linux的記憶體佔用率很大,可能97 以上,我知道這是linux的記憶體使用機制,先將記憶體整個管理起來,需要的時候在分配給單個程序。但是如果我需要檢視系統真實的記憶體佔用率應該怎麼做 如下顯示free是顯示的當前記憶體的使用,m的意思是m位元組來顯示內容.我們來一起...