Beispiele für geringe Speicherauslastung und schwache Arten von PHP-Arrays

黄舟
Freigeben: 2023-03-14 20:22:01
Original
1050 Leute haben es durchsucht

Dieser Artikel stellt hauptsächlich die detaillierte Interpretation der geringen Speicherauslastung und der schwachen Arten von PHP-Arrays vor. Er hat einen gewissen Referenzwert und interessierte Freunde können darauf verweisen.

Die Aufgaben dieser beiden Tage wurden früher als geplant erledigt. Sie können eine Verschnaufpause einlegen, um sich zu beruhigen und PHP gründlich zu lernen. Eigentlich wollte ich ursprünglich etwas über PHP-Leistungsoptimierung lernen, aber ein Satz im Internet schockierte mich: „Die Speicherauslastung des PHP-Arrays ist gering. Ein 100-MB-Speicherarray in der C-Sprache erfordert 1 GB in PHP.“ Verbraucht PHP wirklich so viel Speicher? Deshalb habe ich diese Gelegenheit genutzt, um mehr über die Datentypimplementierung von PHP zu erfahren.

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;;
Nach dem Login kopieren

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.

Im Internet heißt es jedoch, 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;;
Nach dem Login kopieren

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字节*/ 
};
Nach dem Login kopieren

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;
Nach dem Login kopieren

Die Größe des von der Union belegten Speichers Der Typ wird durch den von seinem größten Mitglied belegten Datenraum bestimmt. 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;
Nach dem Login kopieren

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;
Nach dem Login kopieren

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 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.000 Speicher, während ein zweidimensionales Array mit 10.000 Elementen tatsächlich 23 MB verbraucht. Kleine Arrays sind es wirklich nicht wert.

Das obige ist der detaillierte Inhalt vonBeispiele für geringe Speicherauslastung und schwache Arten von PHP-Arrays. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
php
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!