Maison > Article > développement back-end > Analyse de l'utilisation de la mémoire du tableau PHP
Quelle quantité de mémoire l'approche suivante occupera-t-elle ?
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";
Le résultat de l'opération ci-dessus est le suivant :
27.9404MB 51.3041MB 9.1553MB
On peut voir que la mémoire occupée par le tableau est beaucoup plus grand que le contenu normalement alloué
Principe
En PHP, le type long est utilisé pour représenter des nombres, et le type int n'est pas utilisé. Tout le monde comprend que PHP est un langage faiblement typé. Il ne distingue pas le type de variables et n'a pas de concepts tels que int float char *. Jetons un coup d'œil aux variables que PHP stocke dans zend. Chaque variable en PHP a un zval correspondant. La structure Zval est définie dans Zend/zend.h. Sa 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 utilise une structure UNION pour stocker. la valeur de la variable, c'est-à-dire que zvalue_value est une union. La mémoire occupée par la variable UNION est déterminée par l'espace de données maximum du membre.
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;
L'espace de données maximum des membres est struct str, le pointeur occupe 4 octets pour *val et INT occupe 4 octets, pour un total de 8 octets.
L'espace occupé par la structure zval est de 8+4+1+1 = 14 octets. En fait, les tableaux, les chaînes et les objets dans zval nécessitent des structures de stockage supplémentaires, et le tableau est une HashTable :
La structure HashTable est définie dans 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;
La structure HashTable nécessite 39 octets, et chaque élément du tableau est stocké dans la structure Bucket :
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;
Structure Bucket Elle nécessite 33 octets, et la partie avec une longueur de clé supérieure à quatre octets est ajoutée à la fin du bucket, et la valeur de l'élément est probablement une structure zval. De plus, chaque tableau se verra attribuer un tableau de pointeurs de bucket pointés par arBuckets, bien qu'on ne puisse pas dire que chaque augmentation d'un élément nécessite un pointeur, mais la situation pourrait être pire. Cela calcule qu'un élément du tableau occupera 54 octets, ce qui est presque identique à l'estimation ci-dessus.
Un tableau vide occupera au moins 14(zval) + 39(HashTable) + 33(arBuckets) = 86 octets. En tant que variable, il doit avoir une position dans la table des symboles et est également un élément du tableau. , donc une variable de tableau vide nécessite 118 octets pour être décrite et stockée. D'un point de vue spatial, les petits tableaux sont en moyenne plus chers. Bien entendu, un script ne sera pas rempli d'un grand nombre de petits tableaux, et la commodité de la programmation peut être obtenue avec un coût d'espace inférieur. Mais si vous utilisez un tableau comme conteneur, c'est une autre histoire. Dans les applications pratiques, vous rencontrez souvent des tableaux multidimensionnels comportant de nombreux éléments. Par exemple, un tableau unidimensionnel de 10 000 éléments consomme environ 540 Ko de mémoire, tandis qu'un tableau bidimensionnel de 10 000 éléments consomme en réalité 23 Mo, et les petits tableaux n'en valent vraiment pas la peine.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!