PHPMemoryUsage
Bei der Erzeugung eines Trees für die Spracherkennung von Texten bin ich plötzlich an ein Speicherlimit bei 32MB gestoßen und habe nicht schlecht gestaunt, vor allem weil der Tree nicht einmal 10.000 Nodes enthield. Ich benutze PHP 5.2.0, bin also auf dem aktuellen Stand. Um der Sache auf die Spur zu kommen, habe ich eine Analyse angestellt, die mir Klarheit über den Speicherverbrauch bringen soll. Hier das Ergebnis:
Testumgebung
Als Testumgebung dient mir mein Webserver Apache unter Linux mit PHP 5.2.0. Den Speicherverbrauch messe ich mit der Funktion [1], die seit PHP 4.3.2 zur Verfügung steht.
Als erstes gebe ich einfach mal den Speicherverbrauch beim Start eines PHP-Scripts aus:
<? echo memory_get_usage(); ?>
Ergebnis:
83808
memory_get_usage() liefert nicht den tatsächlich vom System angeforderten Speicher zurück, sondern lediglich der tatsächlich von PHP verwendete Speicher. PHP allokiert größere Bereiche und vergibt sie dann Häppchenweise an den Interpreter, sobald dieser Speicher anfordert.
Dieser Speicher wird für die vordefinierten Arrays verwendet wie z.B. $GLOBALS und kann variieren, je nach Kontext des Aufrufs. Was $GLOBALS enthält kann mit folgendem Code ermittelt werden:
<textarea cols=100 rows=20> <?print_r( $GLOBALS );?> </textarea>
Weitere Informationen über vordefinierte Variablen findet man unter Predefined Variables.
Um den Verbrauch zu messen speichere ich alse den Speicherverbrauch beim Start des Scripts in eine Variable und geben am Ende die Differenz aus:
<? $m1 = memory_get_usage(); echo memory_get_usage()-$m1; ?>
Das Ergebnis verblüfft auf den ersten Blick - spontan würde man als Ergebnis eine 0 erwarten, ausgegeben wird aber 72. Es scheint also, als würde die Variable $m1 bereits mit 72 ins Gewicht fallen.
Angenommen, dieser Verdacht wäre richtig: Was wäre dann das Ergebnis folgenden Scripts:
<? $m1 = memory_get_usage(); $m2 = memory_get_usage(); echo $m2-$m1; ?>
Das Ergebnis ist ebenfalls 72 und so scheint es, als wäre es nicht so einfach, nachvollziehbare und erklärbare Ergebnisse zu erhalten. Die Messung hat Einfluss auf das Ergebnis.
Folgender Test macht die Verwirrung komplett:
<? $m1 = memory_get_usage(); $m2 = memory_get_usage(); $m2 = memory_get_usage(); echo $m2-$m1; ?> Das Ergebnis ist 192. Die Variable $m2 wird offenbar erst angelegt, nachdem der Aufruf von memory_get_usage() abgeschlossen ist.
Daraus folgt, dass der ideale Testcode folgendermaßen aufgebaut sein muss:
<? $m1 = memory_get_usage(); $m1 = memory_get_usage(); // add tests from here --> // <-- until here echo memory_get_usage()-$m1; ?>
Das Ergebnis ist tatsächlich 0 wie erwartet. Glücklicherweise belegen Kommentare keinen Speicher ;o)