PHP数组实际占用内存大小的分析
http://blog.csdn.net/hguisu/article/details/7376705
我們在前面的php高效寫法提到,盡量不要復制變量,特別是數組。一般來說,PHP數組的內存利用率只有 1/10, 也就是說,一個在C語言里面100M 內存的數組,在PHP里面就要1G。下面我們可以粗略的估算PHP數組占用內存的大小,首先我們測試1000個元素的整數占用的內存:
<?php echo memory_get_usage() , '<br>'; $start = memory_get_usage(); $a = Array(); for ($i=0; $i<1000; $i++) { $a[$i] = $i + $i; } $mid = memory_get_usage(); echo memory_get_usage() , '<br>'; for ($i=1000; $i<2000; $i++) { $a[$i] = $i + $i; } $end = memory_get_usage(); echo memory_get_usage() , '<br>'; echo 'argv:', ($mid - $start)/1024 ,'kb' , '<br>'; echo 'argv:',($end - $mid)/1024 ,'kb' , '<br>';
輸出是:
350752
435248
519424
argv:84.416byte
argv:84.176byte
大概了解1000 個元素的整數數組需要占用 82k 內存,平均每個元素占用 84 個字節。而純 C 中整體只需要 4k(一個整型占用4byte * 1000 )。memory_get_usage() 返回的結果并不是全是被數組占用了,還要包括一些 PHP 運行本身分配的一些結構,可能用內置函數生成的數組更接近真實的空間:
<?php $start = memory_get_usage(true); $a = array_fill(0, 10000, 1); $mid = memory_get_usage(true); //10k elements array; echo 'argv:', ($mid - $start )/10000,'byte' , '<br>'; $b = array_fill(0, 10000, 1); $end = memory_get_usage(true); //10k elements array; echo 'argv:', ($end - $mid)/10000 ,'byte' , '<br>';
得到:
argv:54.5792byte
argv:54.5792byte
從這個結果來看似乎一個數組元素大約占用了54個左右的字節。再看看數組在Zend里面的C結構,PHP中的數組變量,首先需要一個 zval 結構:
struct _zval_struct {
? ?zvalue_value value;
? ?zend_uint refcount__gc;
? ?zend_uchar type;
? ?zend_uchar is_ref__gc;
};
zvalue_value 是一個union:
typedef union _zvalue_value {
? ?long lval;
? ?double dval;
? ?struct {
? ? ? ?char *val;
? ? ? ?int len;
? ?} str;
? ?HashTable *ht;
? ?zend_object_value obj;
} zvalue_value;
通常 zval 結構需要 8+6=14 個字節,PHP中每個變量都有對應的 zval,但是數組,字符串和對象還需要另外的存儲結構,而數組則是一個 HashTable :
typedef struct _hashtable {
? ? uint nTableSize;
? ? uint nTableMask;
? ? uint nNumOfElements;
? ? ulong nNextFreeElement;
? ? Bucket *pInternalPointer;
? ? Bucket *pListHead;
? ? Bucket *pListTail;
? ? Bucket **arBuckets;
? ? dtor_func_t pDestructor;
? ? zend_bool persistent;
? ? unsigned char nApplyCount;
? ? zend_bool bApplyProtection;
} HashTable;
HashTable 結構需要 40 個字節,每個數組元素存儲在 Bucket 結構中:
typedef struct bucket {
? ? ulong h;
? ? uint nKeyLength;
? ? void *pData;
? ? void *pDataPtr;
? ? struct bucket *pListNext;
? ? struct bucket *pListLast;
? ? struct bucket *pNext;
? ? struct bucket *pLast;
? ? char arKey[1];
} Bucket;
Bucket 結構需要 36 個字節,鍵長超過四個字節的部分附加在 Bucket 后面,而元素值很可能是一個 zval 結構,另外每個數組會分配一個由 arBuckets 指向的 Bucket 指針數組, 雖然不能說每增加一個元素就需要一個指針,但是實際情況可能更糟。這么算來一個數組元素就會占用 54 個字節,與上面的估算幾乎一樣。
? ? 一個空數組至少會占用 14(zval) + 40(HashTable) + 32(arBuckets) = 86 個字節,作為一個變量應該在符號表中有個位置,也是一個數組元素,因此一個空數組變量需要 118 個字節來描述和存儲。從空間的角度來看,小型數組平均代價較大,當然一個腳本中不會充斥數量很大的小型數組,可以以較小的空間代價來獲取編程上的快捷。但如果將數組當作容器來使用就是另一番景象了,實際應用經常會遇到多維數組,而且元素居多。比如10k個元素的一維數組大概消耗540k內存,而10k x 10 的二維數組理論上只需要 6M 左右的空間,但是按照 memory_get_usage 的結果則兩倍于此,[10k,5,2]的三維數組居然消耗了23M,小型數組果然是劃不來的。
總結
以上是生活随笔為你收集整理的PHP数组实际占用内存大小的分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞鹤奶粉多少钱一罐
- 下一篇: nfc标签价格一个多少钱啊?