Home >Backend Development >PHP Tutorial >Continue to discuss PHP array efficiency_PHP tutorial
PHP is sometimes very inefficient in array processing, especially when it takes up a lot of memory, often causing the httpd process to consume too many resources. The bkJia website once called some content and the array was too large, causing the memory to overflow and apache to often crash. Although generally performing a large number of array operations in PHP may reflect programming design problems to a certain extent, it is necessary to roughly estimate the memory occupied by the array.
First feel the memory occupied by an integer array of 1000 elements:
echo memory_get_usage() . “ ”;
$a = Array();
for ($i=0; $i<1000; $i++) {
$a[$i] = $i + $i;
}
echo memory_get_usage() . “ ”;
for ($i=1000; $i<2000; $i++) {
$a[$i] = $i + $i;
}
echo memory_get_usage() . “ ”;
The output is:
58176
162956
267088
You can roughly know that an integer array of 1000 elements requires 100k of memory, and each element occupies an average of 100 bytes. The whole thing in pure C only requires 4k. The results returned by memory_get_usage() are not all occupied by arrays, but also include some structures allocated by PHP itself. The arrays generated by built-in functions may be closer to the real space:
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) . "
”;
Get:
init mem: 58468
10k elements: 724696, system: 786432
10k elements: 1390464, system: 1572864
From this result, it seems that one array element only takes up about 60 bytes. Let’s look at the C structure of the array. Array variables in PHP first require a zval structure:
struct _zval_struct {
zvalue_value value;
zend_uint refcount__gc;
zend_uchar type;
zend_uchar is_ref__gc;
};
zvalue_value is a union:
typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;
Usually the zval structure requires 8+6=14 bytes. Each variable in PHP has a corresponding zval, but arrays, strings and objects also require additional storage structures, and the array is a 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;
The HashTable structure requires 40 bytes, and each array element is stored in the Bucket structure:
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;
The Bucket structure requires 36 bytes, and the part with a key length longer than four bytes is appended to the end of the Bucket, and the element value is likely to be a zval structure. In addition, each array will be allocated a Bucket pointer array pointed to by arBuckets, although it cannot be said Each additional element requires a pointer, but the situation could be worse. This calculates that one array element will occupy 54 bytes, which is not far from the above estimate.
An empty array will occupy at least 14(zval) + 40(HashTable) + 32(arBuckets) = 86 bytes. As a variable, it should have a position in the symbol table and is also an array element, so an empty array Variables require 118 bytes to describe and store. From a space perspective, small arrays are more expensive on average. Of course, a script will not be filled with a large number of small arrays, and programming convenience can be obtained at a smaller space cost.
But if you use an array as a container, it's a different story. In practical applications, you often encounter multi-dimensional arrays with many elements. For example, a one-dimensional array of 10k elements consumes approximately 540k of memory, while a two-dimensional array of 10k The array actually consumes 23M, and small arrays are really not worth it.