Heim > Artikel > Backend-Entwicklung > Analyse der PHP-Array-Speichernutzung
Wie viel Speicher wird der folgende Ansatz beanspruchen?
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";
Die Ausgabe der obigen Operation lautet wie folgt:
27.9404MB 51.3041MB 9.1553MB
Es ist ersichtlich, dass der vom Array belegte Speicher beträgt viel größer als der normalerweise zugewiesene Inhalt
Prinzip
In PHP wird der Typ long zur Darstellung von Zahlen verwendet, der Typ int wird nicht verwendet. Jeder versteht, dass PHP eine schwach typisierte Sprache ist, die den Typ der Variablen nicht unterscheidet und keine Konzepte wie int float char * hat. Werfen wir einen Blick auf die Variablen, die PHP in Zend speichert. Jede Variable in PHP ist in Zend/zend.h definiert. Ihre Struktur:
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 verwendet eine UNION-Struktur zum Speichern Der Wert der Variablen, d. h. zvalue_value, ist eine Union. Der von der UNION-Variablen belegte Speicher wird durch den maximalen Mitgliedsdatenraum bestimmt.
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;
Der maximale Mitgliedsdatenraum ist struct str, der Zeiger belegt 4 Bytes für *val und INT belegt 4 Bytes, also insgesamt 8 Bytes.
Der von struct zval belegte Platz beträgt 8+4+1+1 = 14 Bytes. Tatsächlich erfordern Arrays, Strings und Objekte in zval zusätzliche Speicherstrukturen, und das Array ist eine HashTable:
HashTable-Struktur ist in Zend/zend_hash.h definiert.
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;
HashTable-Struktur erfordert 39 Bytes, und jedes Array-Element wird in Bucket-Struktur gespeichert:
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;
Bucket-Struktur Es erfordert 33 Bytes, und der Teil mit einer Schlüssellänge von mehr als vier Bytes wird an das Ende des Buckets angehängt, und der Elementwert ist wahrscheinlich eine zval-Struktur. Darüber hinaus wird jedem Array ein Array von Bucket-Zeigern zugewiesen, auf die arBuckets zeigt. Man kann zwar nicht sagen, dass jede Erhöhung eines Elements einen Zeiger erfordert, aber die Situation könnte schlimmer sein. Dadurch wird berechnet, dass ein Array-Element 54 Bytes belegt, was fast der obigen Schätzung entspricht.
Ein leeres Array belegt mindestens 14(zval) + 39(HashTable) + 33(arBuckets) = 86 Bytes. Als Variable sollte es eine Position in der Symboltabelle haben und ist auch ein Array-Element , also erfordert eine leere Array-Variable 118 Bytes zum Beschreiben und Speichern. Aus Platzgründen sind kleine Arrays im Durchschnitt teurer. Natürlich wird ein Skript nicht mit einer großen Anzahl kleiner Arrays gefüllt, und der Programmierkomfort kann bei geringeren Platzkosten erreicht werden. Wenn Sie jedoch ein Array als Container verwenden, sieht das anders aus. In praktischen Anwendungen stößt man häufig auf mehrdimensionale Arrays mit vielen Elementen. Beispielsweise verbraucht ein eindimensionales Array mit 10.000 Elementen ungefähr 540 KB Speicher, während ein zweidimensionales Array mit 10.000 Elementen tatsächlich 23 MB verbraucht, und kleine Arrays lohnen sich wirklich nicht.
Das obige ist der detaillierte Inhalt vonAnalyse der PHP-Array-Speichernutzung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!