This article mainly introduces the PHP array memory utilization low and weak type detailed interpretation, with a certain reference value, interested in small partners can refer to.
This two-day task is completed ahead of time, you can take a breather to precipitate a bit, in-depth learning PHP. In fact, I would like to know about PHP performance optimization related things, but by the online sentence "PHP array memory utilization Low, C language 100MB memory array, PHP needs 1G" surprised. Does PHP really consume memory like that? I took this opportunity to learn about the way PHP is implemented in data types.
Let's do a test first:
<?php Echo memory_get_usage (), ' <br> '; $start = Memory_get_usage (); $a = Array (); for ($i =0; $i <1000; $i + +) { $a [$i] = $i + $i; } $end = Memory_get_usage (); Echo memory_get_usage (), ' <br> '; Echo ' argv: ', ($end-$start)/1000, ' bytes ', ' <br> ';
Results obtained:
353352
437848
Argv:84.416bytes
An integer array of 1000 elements consumes memory (437848-353352) bytes, which is approximately 82KB, which means that each element occupies 84 bytes of memory. In C, an int occupies a position of 4 bytes, which is 20 times times the overall difference.
But on the Internet, Memery_get_usage () returns are not all arrays occupied, but also includes some structure of PHP itself, so, in a different way, using PHP built-in function to create an array try:
<?php $start = Memory_get_usage (); $a = Array_fill (0, 10000, 1); $end = Memory_get_usage (); 10k elements Array; Echo ' argv: ', ($end-$start)/10000, ' byte ', ' <br> ';
The output is:
Argv:54.5792byte
Slightly better than just now, but also 54 bytes, really poor 10 times times about.
The reason, but also from the bottom of the PHP implementation. PHP is a weak type of language, without int,double,string and the like, unified a ' $ ' can solve all problems. The PHP bottom is implemented by the C language and each variable corresponds to a zval structure, which is defined in detail as:
typedef struct _ZVAL_STRUCT Zval; struct _zval_struct {/ * Variable information */ zvalue_value value; /* The value 1 12 bytes (32-bit machine is 12, 64-bit machine requires 8+4+4=16) */ Zend_uint refcount__gc;/* The number of references to this value (for GC) 4 bytes */ Zend_uchar type; /* The active Type 1 bytes * /Zend_uchar is_ref__gc;/* Whether This value is a reference (&) 1 bytes */};
PHP uses the union structure to store the values of the variables, and the value variable for the Zvalue_value type in Zval is a union, defined as follows:
typedef Union _ZVALUE_VALUE { long lval; /* Long value */ double dval; /* Double value */ struct {/ * String value */ char *val; int len; } STR; HashTable *ht; /* Hash Table value */ zend_object_value obj; /*object value */} Zvalue_value;
The union type occupies a memory size that is determined by the data space occupied by its largest member. In Zvalue_value, the str struct has an int of 4 bytes, and the char pointer occupies 4 bytes, so the entire Zvalue_value occupies 8 bytes of memory.
The size of the Zval is 8 + 4 + 1 + 1 = 14 bytes.
Notice what another Hashtable is doing in Zvalue_value? In Zval, arrays, strings, and objects also require additional storage structures, and the storage structure of the array is hashtable.
The Hashtable definition gives:
typedef struct _HASHTABLE { uint ntablesize;//table length, not the mask of the number of elements uint ntablemask;//table, always equals nTableSize-1 uint nnumofelements;//the number of elements stored in ulong nnextfreeelement;//refers to the next empty element position in the bucket *pinternalpointer;//foreach loop, Used to record the current traversed element position Bucket *plisthead; Bucket *plisttail; Bucket **arbuckets;//The array of elements stored dtor_func_t pdestructor;//the destructor Zend_bool persistent;//is persisted. From this, it can be found that the PHP array can be persisted in memory without having to reload each request. unsigned char napplycount; Zend_bool bapplyprotection; } HashTable;
In addition to several attribute variables that record table size, the number of elements contained, buckets are used several times, how buckets are defined:
typedef struct BUCKET { ulong H;//array index UINT nkeylength;//The length of the string index void *pdata;//The storage address of the actual data void * Pdataptr; The data storage address of the introduced struct bucket *plistnext; struct bucket *plistlast; struct bucket *pnext; The address of the next element of the doubly linked list struct bucket *plast;//The next element address of the doubly linked list char arkey[1];/* must be the last element */} bucket;
Sort of like a list, buckets are like a list node with specific data and pointers, and Hashtable is an array that holds a bunch of buckets. The implementation of multidimensional arrays in PHP, but there is another hashtable in the bucket.
It takes 39 bytes to calculate a hashtable, and a bucket needs 33 bytes. An empty array needs to occupy 14 + 39 + 33 = 86 bytes. The bucket structure requires 33 bytes, the key length of more than four bytes is appended to the bucket, and the element value is likely to be a zval structure, and each array will be assigned an array of Bucket pointers directed by Arbuckets, although it cannot be said that each additional element requires a pointer , but the situation may be worse. That's all. An array element takes up 54 bytes, almost the same as the estimate above.
From a space point of view, the average cost of small arrays is large, of course, a script will not be flooded with a large number of small arrays, you can take a small space cost to get programming quickly. But if you use an array as a container, it's a different picture, and the actual application often encounters multidimensional arrays, and the elements are mostly. A one-dimensional array of 10k elements, for example, consumes 540k of memory, whereas a two-dimensional array of 10k x 10 theoretically requires only about 6M of space, but according to Memory_get_usage, the three-dimensional array of [10k,5,2] actually consumes 23M, Small arrays are really not going to be scratched.