Analysis of actual memory usage of PHP Arrays

Source: Internet
Author: User

Http://blog.csdn.net/hguisu/article/details/7376705

As mentioned in the previous PHP efficient writing, do not copy variables, especially arrays, whenever possible. In general, the memory usage of PHP arrays is only 1/10. That is to say, an array of 100 MB memory in C language requires 1 GB in PHP. We can roughly estimate the memory occupied by the PHP array. First, we test the memory occupied by the integer of the 1000 elements:

<?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>';  

The output is:

350752
435248
519424
Argv: 84.416 byte
Argv: 84.176 byte

The integer array of 1000 elements occupies 82 KB of memory, and each element occupies 84 bytes on average. In pure C, only 4 K is required (an integer occupies 4 bytes * 1000 ). The results returned by memory_get_usage () are not all occupied by arrays, but also include some structures allocated by PHP running itself. The arrays generated by built-in functions may be closer to the actual space:

<?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>';  

Get:
Argv: 54.5792 byte
Argv: 54.5792 byte

From this result, it seems that an array element occupies about 54 bytes. Let's take a look at the C structure of the array in Zend and the array variable in PHP. First, we need 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;

Generally, the zval structure requires 8 + 6 = 14 bytes. in PHP, each variable has a corresponding zval. However, arrays, strings, and objects also require another storage structure, 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. The key length of more than four bytes is appended to the bucket, and the element value is probably a zval structure, in addition, each array is allocated with a bucket pointer array pointed to by arbuckets. Although it cannot be said that a pointer is required for every addition of an element, the actual situation may be worse. In this case, an array element occupies 54 bytes, almost the same as the above estimation.
An empty array occupies at least 14 (zval) + 40 (hashtable) + 32 (arbuckets) = 86 bytes. As a variable, it should have a position in the symbol table, it is also an array element, so an empty array variable requires 118 bytes to describe and store. From the perspective of space, the average cost of small arrays is relatively high. Of course, a script won't fill a large number of small arrays, so you can get the programming speed at a small space cost. However, using arrays as containers is another scene. In actual applications, multi-dimensional arrays are often used, and many elements exist. For example, a one-dimensional array with 10 k elements consumes about K of memory, while a 10 k x 10 two-dimensional array requires about 6 m in theory, but the results of memory_get_usage are twice the total space, the 3D array of [10 K, 5, 2] actually consumes 23 MB, and small arrays cannot be included.

Http://blog.csdn.net/hguisu/article/details/7376705

As mentioned in the previous PHP efficient writing, do not copy variables, especially arrays, whenever possible. In general, the memory usage of PHP arrays is only 1/10. That is to say, an array of 100 MB memory in C language requires 1 GB in PHP. We can roughly estimate the memory occupied by the PHP array. First, we test the memory occupied by the integer of the 1000 elements:

<?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>';  

The output is:

350752
435248
519424
Argv: 84.416 byte
Argv: 84.176 byte

The integer array of 1000 elements occupies 82 KB of memory, and each element occupies 84 bytes on average. In pure C, only 4 K is required (an integer occupies 4 bytes * 1000 ). The results returned by memory_get_usage () are not all occupied by arrays, but also include some structures allocated by PHP running itself. The arrays generated by built-in functions may be closer to the actual space:

<?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>';  

Get:
Argv: 54.5792 byte
Argv: 54.5792 byte

From this result, it seems that an array element occupies about 54 bytes. Let's take a look at the C structure of the array in Zend and the array variable in PHP. First, we need 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;

Generally, the zval structure requires 8 + 6 = 14 bytes. in PHP, each variable has a corresponding zval. However, arrays, strings, and objects also require another storage structure, 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. The key length of more than four bytes is appended to the bucket, and the element value is probably a zval structure, in addition, each array is allocated with a bucket pointer array pointed to by arbuckets. Although it cannot be said that a pointer is required for every addition of an element, the actual situation may be worse. In this case, an array element occupies 54 bytes, almost the same as the above estimation.
An empty array occupies at least 14 (zval) + 40 (hashtable) + 32 (arbuckets) = 86 bytes. As a variable, it should have a position in the symbol table, it is also an array element, so an empty array variable requires 118 bytes to describe and store. From the perspective of space, the average cost of small arrays is relatively high. Of course, a script won't fill a large number of small arrays, so you can get the programming speed at a small space cost. However, using arrays as containers is another scene. In actual applications, multi-dimensional arrays are often used, and many elements exist. For example, a one-dimensional array with 10 k elements consumes about K of memory, while a 10 k x 10 two-dimensional array requires about 6 m in theory, but the results of memory_get_usage are twice the total space, the 3D array of [10 K, 5, 2] actually consumes 23 MB, and small arrays cannot be included.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.