In C werden malloc und free direkt zum Zuweisen und Freigeben von Speicher verwendet. Wenn Sie malloc jedoch direkt verwenden, führt dies zu einer Speicherfragmentierung und verringert die Systemleistung Eine solche Zuweisung führt zu ernsthaften Leistungsproblemen. Da es sich um eine Anwendung auf Sprachebene handelt, ist dieser Verlust nicht akzeptabel. Daher hat PHP seinen eigenen Speicherpool ZendMM implementiert, um das Problem der häufigen Speicherzuweisung zu lösen freigeben.
Es definiert Speicheroperationen in drei Granularitäten: Block, Seite und Slot. Die Größe jedes Blocks beträgt 2 MB und jede Seite ist 4 KB groß. Ein Block ist in 512 Seiten unterteilt, und jede Seite ist zur Anwendung in mehrere Slots unterteilt Für den Speicher werden je nach Größe der Anwendung unterschiedliche Zuweisungsstrategien implementiert.
riesig: mehr als 2 MB, rufen Sie die Systemzuweisung direkt auf, weisen Sie mehrere Blöcke zu. Weniger als 2044 KB (511 Seiten) Zuweisung Mehrere Seiten
klein: Der Anwendungsspeicher ist weniger als 3092 B. Der Speicherpool hat im Voraus 30 verschiedene Speichergrößen (8, 16, 32 ..., 3072) definiert Auf verschiedenen Seiten können Sie den entsprechenden Steckplatz direkt im entsprechenden Speicher finden. Der Speicherpool speichert die Hauptinformationen des Speicherpools über die Struktur zend_mm_heap, z. B. große Speicherverknüpfungsliste, verknüpfte Speicherliste Liste der einzelnen Slot-Größen usw.
Großer Speicher wird tatsächlich mehreren Blöcken zugewiesen. Dann wird er über eine zend_mm_huge_list-Struktur verwaltet. Eine einseitig verknüpfte Liste wird zwischen großen Speichern gebildet.
Chunk ist die minimale Granularität für Speicherpool zum Beantragen und Freigeben von Speicher aus dem System. Die Adresse des ersten Blocks wird in zend_mm_heap- >main_chunk gespeichert, der Speicher der ersten Seite wird zum Speichern der Strukturmitglieder verwendet der Chunk selbst, wie die Zeiger des vorherigen und nächsten Chunks, die Nutzung jeder Seite des aktuellen Chunks usw.
Slots gleicher Größe bilden eine einfach verknüpfte Liste
Die Initialisierung des Der Speicherpool wird in der Phase „php_module_startup“ abgeschlossen. Der Initialisierungsprozess dient hauptsächlich der Zuweisung der Heap-Struktur. Wenn es sich um eine Multithread-Umgebung handelt, wird jedem Thread ein Speicherpool zugewiesen Threads wirken sich nicht gegenseitig aus. Die Umgebungsvariable use_zend_alloc_huge_pages wird verwendet, um festzulegen, ob große Speicherseiten aktiviert werden sollen. In einer nicht threadsicheren Umgebung wird der zugewiesene Heap in alloc_globals gespeichert, dem AG-Makro. Es ist zu beachten, dass die zend_mm_heap-Struktur nicht separat zugewiesen und in die Chunk-Struktur eingebettet wird, da die Chunk-Struktur eine Seite belegt, aber tatsächlich nicht so viel Speicher verbraucht, um den Platz so weit wie möglich zu nutzen , es wird hier platziert
Speicherzuweisung: 1. Eine große Speicherzuweisung von mehr als 2 MB wird bei der Zuweisung auf n Blöcke ausgerichtet, und es wird auch eine zned_mm_huge_list-Struktur zugewiesen, um den gesamten großen Speicher zu verwalten. Der Speicherausrichtungsprozess wird angepasst nach der Anwendung durch den Speicherpool selbst, nicht einfach. Es wird einmal entsprechend der tatsächlichen Größe angewendet. Wenn die Speicherausrichtung gerade erreicht werden kann, ist keine Anpassung erforderlich, und es wird direkt zur Verwendung zurückgegeben. Wenn es sich nicht um ein ganzzahliges Vielfaches von ZEND_MM_CHUNK_SIZE (2 MB) handelt, gibt zendMM den Speicher frei und befolgt dann die Anweisungen. Der zusätzliche Block wird zur Anpassung verwendet. 2. Große Zuweisung: Wenn die Speichergröße angewendet wird liegt zwischen 3072B (3/4Seiten) und 2044K (511 Seiten), der Speicherpool wird in der Größe gefunden. Die entsprechende Anzahl von Seiten im Block wird zurückgegeben. Die Anwendungsgranularität beträgt page. Es gibt zwei Mitglieder: free_map und map Der Block zum Aufzeichnen der Zuordnungsinformationen der Seite
free_map ist 512 Bit und wird zum Aufzeichnen der Zuordnung von Seiten auf dem Block verwendet. Wenn verwendet, wird er auf 1 gesetzt.
Die Karte wird zum Aufzeichnen des Zuordnungstyps verwendet der Seite und der Anzahl der zugewiesenen Seiten. Die höchsten 2 Bits zeichnen den Zuweisungstyp der Seite auf. 01 ist groß, 10 ist klein und die Zuweisung beginnt mit dem Durchlaufen und prüft, ob Die Blöcke verfügen über Seiten, die den Anforderungen entsprechen. Wenn es bis zum Ende keine passende Seite gibt, weisen Sie einen Block neu zu. Ich weiß es nicht. Wer eine ausreichende Anzahl an Seiten findet, sollte die Chunk-Lücken so weit wie möglich füllen und sie so weit wie möglich mit den zugewiesenen Seiten verbinden, um Seitenlücken in der Mitte zu vermeiden (um die Anzahl der Suchen bei der späteren Zuordnung zu reduzieren) 1) Von Die erste Chunk-Gruppe (0~63) beginnt mit der Überprüfung, ob in der aktuellen Gruppe verfügbare Seiten vorhanden sind, und ermittelt die Positionen der ersten und letzten freien Seiten Seiten als 1 (Zugeordnet), suchen Sie nach anderen Gruppen, verwenden Sie sie direkt und unterbrechen Sie den Abruf. Wenn die Seite größer als erforderlich ist, bedeutet dies, dass sie verfügbar ist, aber nicht optimal ist um nach anderen Blöcken zu suchen, bis schließlich ein optimaler gefunden wird ((kann die Nutzung der Seite maximieren) 2) Nachdem Sie die entsprechende Seite gefunden haben, legen Sie die entsprechenden Seiteninformationen fest, dh free_map und Karteninformationen, und geben Sie dann die Seitenadresse zurück 3 . Kleine Zuweisung:
Prüft zunächst, ob der Speicher der entsprechenden Spezifikationen zugewiesen wurde. Wenn er nicht zugewiesen ist oder die Zuweisung aufgebraucht ist, ist der Seitenzuweisungsprozess derselbe Bei einer großen Zuordnung wird die Seite entsprechend der festen Größe in Slots unterteilt und der Kopf der verknüpften Liste wird in AG(mm_heap)-> gespeichert. free_slot
Die Granularität der Speicherpoolfreigabe ist Chunk, die durch efree 1 abgeschlossen wird. Die Freigabe großer, großer und kleiner Speichertypen erfolgt, weil die erste Seite des Chunks belegt ist, sodass ein Offset von 0 nicht möglich ist relativ zum Block, daher wird unterschieden: Beim Freigeben des Blocktyps und der großen und kleinen Typen wird der belegte Block gleichzeitig freigegeben und aus der AG-verknüpften Liste gelöscht. 2. Freigabe des großen Speichers: Wenn der berechnete Offset Ist nicht 0, bedeutet dies, dass es sich bei der Adresse um einen großen oder kleinen Speicher handelt. Anschließend wird die Seitennummer anhand des Offsets berechnet. Nach dem Abrufen der Seite können Sie den Zuordnungstyp der Seite aus der Chunk-> Map abrufen Geben Sie den Speicher des angegebenen Typs frei, setzen Sie jedoch die Zuordnungsinformationen der Seite auf Nicht zugewiesen. Wenn festgestellt wird, dass der Block nicht zugewiesen ist, wird er freigegeben Wenn die Cache-Nummer einen bestimmten Wert erreicht, wird der neu hinzugefügte Block nicht mehr zwischengespeichert und der Speicher zurückgegeben. Vermeiden Sie es, zu viel Speicher zu belegen, wenn ein zwischengespeicherter Block vorhanden ist Es befindet sich in chached_chunks und kann direkt herausgenommen und verwendet werden, ohne dass eine Anwendung im System erforderlich ist. 3. Geben Sie den freigegebenen Steckplatz direkt wieder in die verfügbare verknüpfte Liste des Regelsteckplatzes ein, es ist relativ einfach
In C werden malloc und free direkt zum Zuweisen und Freigeben von Speicher verwendet. Wenn Sie malloc jedoch direkt verwenden, führt dies zu einer Speicherfragmentierung und verringert die Systemleistung Eine solche Zuweisung führt zu ernsthaften Leistungsproblemen. Da es sich um eine Anwendung auf Sprachebene handelt, ist dieser Verlust nicht akzeptabel. Daher hat PHP einen eigenen Speicherpool ZendMM implementiert, um das Problem der häufigen Speicherzuweisung zu lösen 🎜>
Es definiert drei granulare Speicheroperationen: Block, Seite und Slot. Die Größe jedes Blocks beträgt 2 MB und jede Seite ist in 512 Seiten unterteilt, und jede Seite ist in mehrere Slots unterteilt . Bei der Beantragung von Speicher werden je nach Größe der Anwendung unterschiedliche Zuweisungsstrategien implementiert
riesig: größer als 2 MB, rufen Sie direkt die Systemzuweisung auf, weisen Sie mehrere Blöcke zu
groß: beantragen Sie Speicher größer als 3092 B (3/ 4 Seiten), weniger als 2044 KB (511 Seiten), mehrere Seiten zuweisen
klein: Für Speicher mit weniger als 3092 B gelten, der Speicherpool hat im Voraus 30 verschiedene Speichergrößen definiert (8, 16, 32 ..., 3072). werden auf verschiedene Weise verteilt. Suchen Sie bei der Speicherbeantragung direkt nach dem entsprechenden Steckplatz im entsprechenden Speicher. Der Speicherpool speichert die Hauptinformationen des Speicherpools über die Struktur zend_mm_heap, z. B. große Speicherverknüpfungsliste, Chunk-Verknüpfungsliste usw. Speicherverknüpfte Liste jeder Steckplatzgröße usw.
Große Speicherzuweisung Es handelt sich tatsächlich um mehrere Blöcke, die dann über eine zend_mm_huge_list-Struktur verwaltet werden. Eine einseitig verknüpfte Liste wird zwischen großen Speichern gebildet.
Chunk ist die minimale Granularität Für den Speicherpool wird eine doppelt verknüpfte Liste zwischen den Blöcken erstellt. Die Adresse des Blocks wird in zend_mm_heap->main_chunk gespeichert Strukturelemente des Blocks selbst, wie z. B. die Zeiger des vorherigen und nächsten Blocks, die Verwendung jeder Seite des aktuellen Blocks usw.
Zwischen Slots gleicher Größe Bilden einer einfach verknüpften Liste
Die Initialisierung des Speicherpools wird in der Phase php_module_startup abgeschlossen. Der Initialisierungsprozess wird hauptsächlich im Prozess start_memory_manager abgeschlossen. Wenn es sich um eine Multithread-Umgebung handelt, wird jedem Thread ein Speicherpool zugewiesen. Während der Initialisierung wird die Umgebungsvariable use_zend_alloc_huge_pages verwendet, um festzulegen, ob große Speicherseiten aktiviert werden sollen. In einer nicht threadsicheren Umgebung wird der zugewiesene Heap in alloc_globals, dem AG-Makro, gespeichert. Es ist zu beachten, dass die zend_mm_heap-Struktur nicht separat zugewiesen wird, sondern in die Chunk-Struktur eingebettet ist, da die Chunk-Struktur eine Seite belegt, aber tatsächlich nicht so viel Speicher verwendet, um den Speicherplatz so gut wie möglich zu nutzen Möglicherweise wird es hier platziert
Speicherzuweisung: 1. Eine große Speicherzuweisung von mehr als 2 MB wird bei der Zuweisung auf n Blöcke ausgerichtet, und eine zned_mm_huge_list-Struktur wird ebenfalls zugewiesen, um den gesamten großen Speicher zu verwalten. Der Prozess der Speicherausrichtung Ist der Speicherpool selbst nach der Anwendung Die Anpassung erfolgt nicht einfach durch das Betriebssystem. Es wird nur einmal entsprechend der tatsächlichen Größe angewendet. Wenn die Speicherausrichtung einfach erreicht werden kann, ist keine Anpassung erforderlich, und sie wird direkt zur Verwendung zurückgegeben . Wenn es sich nicht um ein ganzzahliges Vielfaches von ZEND_MM_CHUNK_SIZE (2 MB) handelt, wird es von zendMM entsprechend der tatsächlichen Speichergröße + ZEND_MM_CHUNK_SIZE freigegeben. Große Zuordnung: Die angewendete Speichergröße liegt zwischen 3072 B (3/4 Seiten) und 2044 KB (511 Seiten). Der Speicherpool sucht nach der entsprechenden Anzahl von Seiten im Block und gibt diese zurück. Es gibt zwei Mitglieder, free_map und map, um die Zuordnungsinformationen der Seite aufzuzeichnen.
free_map ist 512 Bit und wird zum Aufzeichnen des Zuordnungsstatus der Seite auf dem Block verwendet auf 1 gesetzt
Die Karte wird verwendet, um den Zuordnungstyp der Seite und die Anzahl der zugewiesenen Seiten aufzuzeichnen. Die höchsten 2 Bits zeichnen den Zuordnungstyp der Seite auf Wenn Sie klein sind, beginnen Sie mit der Durchquerung des ersten Blocks und prüfen Sie, ob der aktuelle Block über eine geeignete Seite verfügt Wenn ich einen Block bewerbe, weiß ich nicht, wer genügend Seiten gefunden hat. Stattdessen versuche ich, die Lücken im Block so weit wie möglich zu füllen und sie so weit wie möglich mit den zugewiesenen Seiten zu verbinden Seitenlücken in der Mitte (um die Zeit für die nachfolgende Zuweisung zu verkürzen) 1) Beginnen Sie mit der Überprüfung ab der ersten Blockgruppe (0 bis 63). Erkennen Sie zunächst die Bits der aktuellen Gruppe Seite und finden Sie die Positionen der ersten und letzten freien Seiten. Wenn diese nicht ausreichen, werden diese Seiten als 1 (zugewiesen) markiert und andere Gruppen werden durchsucht. Wenn die Seite genau richtig ist, wird sie direkt verwendet und abgerufen Wenn die Seite größer als erforderlich ist, bedeutet dies, dass sie verfügbar ist, aber nicht optimal ist, und bis zum Ende wird nach anderen Teilen gesucht (derjenige, der die Nutzung der Seite maximieren kann). ) Nachdem Sie die entsprechende Seite gefunden haben, legen Sie die entsprechenden Seiteninformationen fest, dh free_map und Karteninformationen, und geben Sie dann die Seitenadresse zurück. 3. Kleine Zuweisung:
prüft zuerst die entsprechende Seite. Ob der angegebene Speicher zugewiesen wurde? Ist die Zuteilung nicht erfolgt oder die Zuteilung aufgebraucht, erfolgt die Beantragung von Seiten mit der entsprechenden Seitenanzahl wie bei einer großen Zuteilung. Nach der Beantragung der Seite wird diese entsprechend aufgeteilt Feste Größe und einzelne Slots werden zwischen den Slots verwendet. Verknüpfte Listenverbindung, der Kopf der verknüpften Liste wird in AG(mm_heap)->free_slot
gespeichertDie Granularität der Speicherpoolfreigabe ist Chunk, die durch efree 1 abgeschlossen wird. Die Freigabe großer, großer und kleiner Speichertypen ist darauf zurückzuführen, dass die erste Seite des Blocks belegt ist, sodass ein relativer Offset von 0 nicht möglich ist zum Block, damit unterschieden werden kann. Beim Freigeben des Blocktyps sowie der großen und kleinen Typen wird der belegte Block gleichzeitig freigegeben und aus der AG-verknüpften Liste gelöscht. 2. Freigabe des großen Speichers: Wenn der berechnete Offset Ist nicht 0, bedeutet dies, dass die Adresse groß oder klein ist. Berechnen Sie dann die Seitennummer anhand des Offsets. Nachdem Sie die Seite erhalten haben, können Sie den Zuordnungstyp der Seite aus der Chunk-> Map abrufen Geben Sie den Speicher des angegebenen Typs frei, setzen Sie jedoch die Zuordnungsinformationen der Seite auf Nicht zugewiesen. Wenn festgestellt wird, dass der Block nicht zugewiesen ist, wird er freigegeben Wenn die Cache-Nummer einen bestimmten Wert erreicht, wird der neu hinzugefügte Block nicht mehr zwischengespeichert und der Speicher zurückgegeben. Vermeiden Sie es, zu viel Speicher zu belegen, wenn ein zwischengespeicherter Block vorhanden ist In chached_chunks wird es direkt herausgenommen und verwendet, ohne dass eine Anwendung im System 3 erforderlich ist. Bei der Freigabe kleinerer Typen wird der freigegebene Steckplatz direkt wieder in die verfügbare verknüpfte Liste des Regelsteckplatzes eingefügt einfach.
Verwandte Empfehlungen:
Erläuterung von JS-Speicherverwaltungsbeispielen
Detaillierte Einführung in die Speicherverwaltung unter Linux
Studiennotizen zu PHP-Variablen und Speicherverwaltung
Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung der PHP-Speicherverwaltung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!