phpbar.de logo

Mailinglisten-Archive

[php] Speicherverwaltung unter PHP!

[php] Speicherverwaltung unter PHP!

Johannes Schlueter schlueter at phpbar.de
Die Sep 27 09:35:23 CEST 2005


Hi,

On Monday 26 September 2005 14:59, Andre Manikofski wrote:
> Wenn ich ein lägeres Skript programmiert habe und während der
> Programmierung im Quelltext mit UNSET ()- Variablen freigegebe, wird dann
> in Echtzeit "quasi" Speicher frei oder wird dies erst am Ende eines
> Skripten durch den PHP- Interpreter vollzogen?

Kurze Antwort: Ja, beides.

Etwas längere Antwort: Zunächst musst Dir die Grundlegende Geschichte bzgl. 
refcount klar machen: Die Zuweisung $a = $b; führt nicht zu einem doppelten 
Speicherverbrauch. Stattdessen wird in der Variablentabelle ein neuer Eintrag 
angelegt, der auf eine existierenden Variablenspeicher in diesem 
Speicherbereich (dem sogenannten zval) wird ein Flag "refcount" hochgesetzt 
erst bei Zuweisung eines neuen Werts auf eine Variable wird die separiert und 
der neue Speicher belegt. Damit unset was bringen kann müssen alle internen 
Referenzen auf eine Variable entsorgt werden. Dann wird der Speicher wieder 
freigegeben - ah so einfach ist das dann auch wieder nicht. Da das anfordern 
von neuem Speicher vom Betriebssystem recht lange dauert gibt es da 
(insbesondere in jüngeren Versionen) wieder Optimierungen, namentlich den 
Zend Memory Manager, die dafür sorgen, dass der Speicher nicht unnötig 
freigegeben und dann gleich wieder angefordert wird. Aber er wird auch wieder 
freigegeben, evtl. etwas Zeitversetzt in größerer Menge.

Wenn Du also größere Datenstrukturen freigibst kann das sehr wohl was bringen. 
Hier und da ne einzelne Variable bringt fast nichts...

Falls Dein Skript über längere Zeit (Tage?) läuft gibt es noch ein paar 
Fallstricke die zu stetig wachsendem Speicherverlauf führen können. a) Bugs 
und b) kleinere leaks die schwer zu tracken sind und von den Entwicklern als 
nicht so tragisch angesehen werden.

Zur letzteren Gruppe fällt mir ein knappes PHP 5 Beispiel ein:
<?php
try {
    while ($a != 42) {
        // ...
        throw new Exception("blubber");
       // ...
    }
} catch (Exception $e) {
    ...
}
?>

hier wird, durch die Exception aus der while-Schleife herausgesprungen. Da 
bleiben wenige Byte interne Arbeitsdaten der while-Schleife unaufgeräumt. 
Dies wird als weniger kritisch angesehen, da eine Exception ienen 
Ausnahme-Zustand bedeutet der, so man Exceptions nicht für Control-Flow 
missbraucht, nicht sonderlich oft auftreten sollte.

Komplett aufgeräumt wird am Skriptende. (Nungut, auch nicht 100%ig da kann es 
unter ungünstigen Umständen usw. auch mal den ein oder anderen Bug, 
insbesondere in externen libs¹, geben der zu einem leak führt...)

Hoffe etwas geholfen zu haben,
johannes

[¹] Das mit den externen libs hängt nicht damit zusammen, dass die PHP 
Entwickler besonders toll und die anderen schlecht sind sondern, dass PHP/die 
Zend Engine einen Mechanismus hat, der sich merkt welcher Speicher für die 
Skript-Verarbeitung eines Requests angefordert wird und wenn da irgendwo der 
free vergessen wurde am Request-Ende einspringt. Dieser Mechanismus wird aber  
i.d.R. nicht von externen libs genutzt (und als Nebenbemerkung: nur über 
diesen Mechanismus angeforderter Speicher zählt bei memory_limit&co)

php::bar PHP Wiki   -   Listenarchive