繼續來討論PHP陣列效率問題

2021-12-29 20:36:36 字數 2046 閱讀 2885

php在陣列處理上有時候會非常低效,尤其是記憶體占用較多,常常使得httpd程序消耗太多資源。php100**就曾因為呼叫一些內容,陣列過大,導致記憶體據增溢位,apache經常癱瘓。雖然通常在php中進行大量陣列運算從一定程度上反應程式設計上可能存在問題,但是粗略的估計陣列占用的記憶體是很有必要的。

首先感覺一下1000個元素的整數陣列占有的記憶體:

echo memory_get_usage() . 「

」;$a = array();

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

echo memory_get_usage() . 「

」;for ($i=1000; $i<2000; $i++)

echo memory_get_usage() . 「

」;輸出是:

58176

162956

267088

大 約可以知道 1000 個元素的整數陣列需要占用 100k 記憶體,平均每個元素占用 100 個位元組。而純 c 中整體只需要 4k。memory_get_usage() 返回的結果並不是全是被陣列占用了,還要包括一些 php 執行本身分配的一些結構,可能用內建函式生成的陣列更接近真實的空間:

echo 「init mem: 」 . memory_get_usage() . 「

」;$a = array_fill(0, 10000, 1);

echo 「10k elements: 」 . memory_get_usage() . 「, system: 」 . memory_get_usage(true) . 「

」;$b = array_fill(0, 10000, 1);

echo 「10k elements: 」 . memory_get_usage() . 「, system: 」 . memory_get_usage(true) . 「

」;得到:

init mem: 58468

10k elements: 724696, system: 786432

10k elements: 1390464, system: 1572864

從這個結果來看似乎乙個陣列元素大約只占用了 60 個左右的位元組。再看看陣列的c結構,php 中的陣列變數,首先需要乙個 zval 結構:

struct _zval_struct ;

zvalue_value 是乙個union:

typedef union _zvalue_value str;

hashtable *ht;

zend_object_value obj;

} zvalue_value;

通常 zval 結構需要 8+6=14 個位元組,php中每個變數都有對應的 zval,但是陣列,字串和物件還需要另外的儲存結構,而陣列則是乙個 hashtable :

typedef struct _hashtable hashtable;

hashtable 結構需要 40 個位元組,每個陣列元素儲存在 bucket 結構中:

typedef struct bucket 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遍歷陣列效率分析

要求 兩個分別有5000個元素的陣列,計算它們的差集。普通 function arr diff arr1,arr2 return arr1 高效 function arr diff arr1,arr2 return arr1 要求 判斷某個值是否在陣列中 function i ists key,ar...

使用陣列 指標的效率問題

陣列與指標之間的關係 陣列名的是乙個指標常量 當你根據某個固定數目的增量在乙個陣列中移動時,使用指標變數將比使用下標產生效率更改的 當這個增量是1並且具有位址自動增量模型時,這點表現的更為突出。宣告為暫存器變數的指標通常比位於靜態記憶體和堆疊中的指標效率更高。如果你可以通過測試一些已經初始化並經過調...

PHP陣列問題,求助!

有這樣乙個陣列 array array 0 array day 2014 3 11 count 4,day 0 3,day 1 1,1 array day 2014 3 7 count 2,day 0 1,2 array day 2014 3 6 count 4,day 4 1,day 5 1,3 ...