Home >Backend Development >PHP Tutorial >PHP array memory usage analysis

PHP array memory usage analysis

藏色散人
藏色散人forward
2019-12-09 17:54:092373browse

How much memory will the following approach take up?

list($appid,$openid) = ["testcontent","test"];

Test

$m0 = memory_get_usage();
$k = range(1,200000);
$m1 = memory_get_usage();
echo round(($m1-$m0)/pow(1024,2),4) ."MB\n";
foreach ($k as $i){
    $n1 = "kk$i";
    $n2 = "tt$i";
    list($$n1,$$n2) = [$i,$i*3];
}
$m2 = memory_get_usage();
echo round(($m2-$m1)/pow(1024,2),4) ."MB\n";
$m1 = memory_get_usage();
foreach ($k as $i){
    $n1 = "kk$i";
    $n2 = "tt$i";
    $$n1 = $i+time();
    $$n2 = 2*time();
}
$m2 = memory_get_usage();
echo round(($m2-$m1)/pow(1024,2),4) ."MB\n";

The results of the above operation output are as follows:

27.9404MB
51.3041MB
9.1553MB

It can be seen that the memory occupied by the array is much larger than the normally allocated content

Principle

In PHP, the long type is used to represent numbers, and the int type is not used. Everyone understands that PHP is a weakly typed language. It does not distinguish the type of variables and has no concepts such as int float char *. Let's take a look at the variables PHP stores in zend. Each variable in PHP has a corresponding zval. The Zval structure is defined in Zend/zend.h. Its structure:

typedef struct _zval_struct zval;  
struct _zval_struct {  
    /* Variable information */  
    zvalue_value value;     /* The value 1 12字节(32位机是12,64位机需要8+4+4=16) */  
    zend_uint refcount__gc; /* The number of references to this value (for GC) 4字节 */  
    zend_uchar type;        /* The active type 1字节*/  
    zend_uchar is_ref__gc;  /* Whether this value is a reference (&) 1字节*/  
};

PHP uses a UNION structure To store the value of the variable, that is, zvalue_value is a union. The memory occupied by the UNION variable is determined by the maximum member data space.

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 largest member data space is struct str, the pointer occupies 4 bytes for *val, and INT occupies 4 bytes, for a total of 8 bytes.

The space occupied by struct zval is 8 4 1 1 = 14 bytes. In fact, arrays, strings and objects in zval require additional storage structures. The array is a HashTable:

The HashTable structure is defined in Zend/zend_hash.h.

typedef struct _hashtable {  
    uint nTableSize;//4  
    uint nTableMask;//4  
    uint nNumOfElements;//4  
    ulong nNextFreeElement;//4  
    Bucket *pInternalPointer;   /* Used for element traversal 4*/  
    Bucket *pListHead;//4  
    Bucket *pListTail;//4  
    Bucket **arBuckets;//4  
    dtor_func_t pDestructor;//4  
    zend_bool persistent;//1  
    unsigned char nApplyCount;//1  
    zend_bool bApplyProtection;//1  
#if ZEND_DEBUG  
    int inconsistent;//4  
#endif  
} HashTable;

The HashTable structure requires 39 bytes, and each array element is stored in the Bucket structure:

typedef struct bucket {  
    ulong h;    /* Used for numeric indexing                4字节 */  
    uint nKeyLength;    /* The length of the key (for string keys)  4字节 */  
    void *pData;        /* 4字节*/  
    void *pDataPtr;         /* 4字节*/  
    struct bucket *pListNext;  /* PHP arrays are ordered. This gives the next element in that order4字节*/  
    struct bucket *pListLast;  /* and this gives the previous element           4字节 */  
    struct bucket *pNext;      /* The next element in this (doubly) linked list     4字节*/  
    struct bucket *pLast;      /* The previous element in this (doubly) linked list     4字节*/  
    char arKey[1];            /* Must be last element   1字节*/  
} Bucket;

The Bucket structure requires 33 Bytes, the part with a key length exceeding 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 an array of Bucket pointers pointed to by arBuckets, although it cannot be said that every time an element is added, A pointer is required, but the situation could be worse. This calculates that one array element will occupy 54 bytes, which is almost the same as the above estimate.

An empty array will occupy at least 14(zval) 39(HashTable) 33(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 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 about 540k of memory, while a 10k The array actually consumes 23M, and small arrays are really not worth it.

The above is the detailed content of PHP array memory usage analysis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete