Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Analyse der geringen Speicherauslastung des PHP-Arrays

Detaillierte Analyse der geringen Speicherauslastung des PHP-Arrays

小云云
小云云Original
2018-01-30 10:11:361711Durchsuche

Verbrauch PHP wirklich so viel Speicher? Deshalb habe ich diese Gelegenheit genutzt, um mehr über die Datentypimplementierung von PHP zu erfahren. In diesem Artikel wird hauptsächlich die detaillierte Interpretation der geringen Speicherauslastung und der schwachen Arten von PHP-Arrays vorgestellt. Er hat einen gewissen Referenzwert und interessierte Freunde können darauf verweisen.

Lass uns zuerst einen Test machen:


<?php 
  echo memory_get_usage() , &#39;<br>&#39;; 
  $start = memory_get_usage(); 
  $a = Array(); 
  for ($i=0; $i<1000; $i++) { 
   $a[$i] = $i + $i; 
  } 
  $end = memory_get_usage(); 
  echo memory_get_usage() , &#39;<br>&#39;; 
  echo &#39;argv:&#39;, ($end - $start)/1000 ,&#39;bytes&#39; , &#39;<br>&#39;;

Die erhaltenen Ergebnisse:

353352
437848
argv:84.416bytes

Ein ganzzahliges Array mit 1000 Elementen verbraucht (437848 - 353352) Bytes Speicher, was ungefähr 82 KB entspricht, was bedeutet, dass jedes Element 84 Bytes Speicher belegt. In der C-Sprache belegt ein int 4 Bytes, was insgesamt einem 20-fachen Unterschied entspricht.

Aber im Internet heißt es, dass die von „memory_get_usage()“ zurückgegebenen Ergebnisse nicht alle von Arrays belegt sind, sondern auch einige Strukturen von PHP selbst enthalten. Versuchen Sie es daher auf andere Weise und verwenden Sie PHP-Built. in Funktionen zum Generieren von Arrays:


<?php 
  $start = memory_get_usage(); 
  $a = array_fill(0, 10000, 1); 
  $end = memory_get_usage(); //10k elements array; 
  echo &#39;argv:&#39;, ($end - $start )/10000,&#39;byte&#39; , &#39;<br>&#39;;

Die Ausgabe ist:

argv:54.5792byte

Es ist etwas besser als zuvor, aber es sind immer noch 54 Bytes, was ungefähr das Zehnfache ist.

Der Grund muss bei der zugrunde liegenden Implementierung von PHP liegen. PHP ist eine schwach typisierte Sprache. Unabhängig von int, double, string usw. kann ein einheitliches „$“ alle Probleme lösen. Die unterste Ebene von PHP ist in der C-Sprache implementiert. Jede Variable entspricht einer zval-Struktur, die im Detail wie folgt definiert ist:


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 die Union-Struktur, um Speichern Sie den Wert der Variablen zval. Die Wertvariable vom Typ zvalue_value ist eine Union, die wie folgt definiert ist:


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;

Die Größe des von der Union belegten Speichers Der Typ wird durch den Datenraum bestimmt, der von seinem größten Mitglied belegt wird. In zvalue_value belegt das int der str-Struktur 4 Bytes und der char-Zeiger 4 Bytes, sodass der vom gesamten zvalue_value belegte Speicher 8 Bytes beträgt.

Die Größe von zval beträgt 8 + 4 + 1 + 1 = 14 Bytes.

Beachten Sie, dass es in zvalue_value auch eine HashTable gibt. Was macht sie? In zval erfordern Arrays, Strings und Objekte außerdem zusätzliche Speicherstrukturen. Die Speicherstruktur von Arrays ist HashTable.

HashTable-Definition ergibt:


typedef struct _hashtable { 
   uint nTableSize; //表长度,并非元素个数 
   uint nTableMask;//表的掩码,始终等于nTableSize-1 
   uint nNumOfElements;//存储的元素个数 
   ulong nNextFreeElement;//指向下一个空的元素位置 
   Bucket *pInternalPointer;//foreach循环时,用来记录当前遍历到的元素位置 
   Bucket *pListHead; 
   Bucket *pListTail; 
   Bucket **arBuckets;//存储的元素数组 
   dtor_func_t pDestructor;//析构函数 
   zend_bool persistent;//是否持久保存。从这可以发现,PHP数组是可以实现持久保存在内存中的,而无需每次请求都重新加载。 
   unsigned char nApplyCount; 
   zend_bool bApplyProtection; 
} HashTable;

Zusätzlich zu mehreren Attributvariablen, die die Größe der Tabelle und die Anzahl ihrer Elemente aufzeichnen enthält, Bucket ist Es wurde schon oft verwendet, wie Bucket definiert ist:


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]; /* Must be last element */ 
} Bucket;

ist ein bisschen wie eine verknüpfte Liste, Bucket ist wie ein verknüpfter Listenknoten, mit spezifischen Daten und Zeigern, und HashTable ist ein Array, das eine Liste von Bucket-Elementen enthält. Die Implementierung mehrdimensionaler Arrays in PHP ist nur eine weitere im Bucket gespeicherte HashTable.

Berechnen Sie, dass HashTable 39 Bytes und Bucket 33 Bytes belegt. Ein leeres Array nimmt 14 + 39 + 33 = 86 Bytes ein. Die Bucket-Struktur 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 Bucket-Zeiger zugewiesen Array, auf das arBuckets zeigt, obwohl nicht gesagt werden kann, dass jedes zusätzliche Element 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.

Aus Platzgründen sind die durchschnittlichen Kosten für kleine Arrays relativ hoch. Natürlich wird ein Skript nicht mit einer großen Anzahl kleiner Arrays gefüllt, und Sie können bei einer kleineren Anzahl an Programmierkomfort gewinnen Platzkosten. Wenn Sie jedoch ein Array als Container verwenden, sieht es 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.000 Speicher, während ein 10.000-köpfiges Array tatsächlich 23 MB verbraucht. Kleine Arrays sind es wirklich nicht wert.

Der Grund für die geringe Speicherauslastung von PHP-Arrays wurde hier erwähnt. Im folgenden Artikel wird die spezifische Implementierung von PHP-Array-Operationen erläutert.

Verwandte Empfehlungen:

Lösung für das Problem des zu hohen PHP-Array-Speicherverbrauchs_PHP-Tutorial

Lösen Sie das Problem, dass das PHP-Array zu viel Speicher verbraucht

Lösung für das Problem, dass das PHP-Array zu viel Speicher verbraucht_php-Tipps

Das obige ist der detaillierte Inhalt vonDetaillierte Analyse der geringen Speicherauslastung des PHP-Arrays. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn