PHP Optimierung



  • Da es heute ein bisschen wenig zu tun gibt in der Firma dachte ich, ich beschäftige mich mal mit etwas ganz "seltsamen": PHP Speicheroptimierung.

    Ich erzeuge mit einer For-Schleife 100.000 Int-Variablen. Das hat einen Speicherverbrauch von 8 MB zur Folge.
    Testhalber habe ich der Schleife eine Bedingung verpasst, welche den Speicher der zweiten 50% der Variablen direkt wieder freigibt. Folge: nur mehr 4 MB Speicher belegt und gut um 0.02 Sekunden schneller als die "unfreigegebene Variante".

    Jetzt ist mir aber aufgefallen, dass wenn ich statt unset eine eigene Funktion zur Freigabe verwende, bleibt der Speicher unberührt - sprich weitehrin 8 MB belegt, obwohl es ja nur 4 sein sollten.

    Quellcode dazu:

    <?php
    function relmem($_) {
        unset($_);
    }
    
    $start = microtime();
    $start = explode(' ', $start);
    $start = $start[1] + $start[0];
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
    
    for($i = 0; $i <= 100000; $i++) {
        $v{$i} = (int)$i;
    
        if($i >= 50000) {
            relmem($v{$i});
        }
    }
    
    echo round((memory_get_usage()/1024/1024), 2) . ' KBytes';
    
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
    $end = microtime();
    $end = explode(' ', $end);
    $end = $end[1] + $end[0];
    printf(" - executed in: %f10 seconds", $end - $start);
    ?>
    

    Die relmem()-Funktion ist mein Alias für unset und eben nur testhalber da.

    Mich interessiert jetzt eigentlich nur, warum der Speicher gleich groß bleibt.



  • Da ist noch ein kleiner Schönheitsfehler vom Anfang drin: neben get_memory_usage() steht natürlich MBytes, nicht KBytes. Am Anfang reichten KBytes irgendwie noch ;p



  • Hallo,

    wenn ich nicht komplett daneben liege würde ich sagen, dass du eine Kopie übergibst. Heißt du löschst wenn überhaupt nur die Kopie. Um nun aber direkt die Variable zu löschen solltest du eine Referenz übergeben, die dann direkt auf den Speicher der Variablen zugreift. Das ganze sollte dann so aussehen:

    <?php
    function relmem(&$_) {    // & für Referenz
        unset($_);
    }
    
    $start = microtime();
    $start = explode(' ', $start);
    $start = $start[1] + $start[0];
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
    
    for($i = 0; $i <= 100000; $i++) {
        $v{$i} = (int)$i;
    
        if($i >= 50000) {
            relmem($v{$i});
        }
    }
    
    echo round((memory_get_usage()/1024/1024), 2) . ' KBytes';
    
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
    $end = microtime();
    $end = explode(' ', $end);
    $end = $end[1] + $end[0];
    printf(" - executed in: %f10 seconds", $end - $start);
    ?>
    

    Habs nicht getestet, aber sollte funktionieren.

    Gruß Christopher



  • Hey,

    auch mit der Übergabe einer Referenz ändert sich nichts. Aber ich habe den Grund inzwischen rausgefunden:
    unset innerhalb einer Funktion bezieht sich nur auf Variablen innerhalb der Funktion selbst. Umgehen kann man das ganze durch $GLOBALS, damit man zum allgemeinen Gültigkeitsbereich kommt. Zwar nicht sonderlich schön, aber so funktioniert es immerhin.


  • Mod

    Ich würde eher hinterfragen warum du soviele Variablen brauchst.



  • Ich brauche nicht so viele Variablen - mich hat einfach mal die Thematik selbst interessiert. Und testbedingt sind zig Tausend Variablen ersichtlicher als ein paar Wenige.

    Wie gesagt, das war ein reiner Test. Mehr nicht. 😉



  • Die beste Variante, PHP zu optimieren, besteht immer noch darin, es zu ersetzen.



  • 314159265358979 schrieb:

    Die beste Variante, PHP zu optimieren, besteht immer noch darin, es zu ersetzen.

    Und mit was bitte?



  • CGI (C, C++, ...), Perl, Python, .NET, JSP, Scala, ...
    Such dir was aus 😉



  • Wenn du dir nicht gerade deinen eigenen Server aufsetzt, hast du die alle aber oft nicht. 😉
    Python und Perl sind nicht umbedingt schneller als PHP. C/C++ sind imho ein Krampf bei der Webentwicklung, Java ist im Prinzip ganz nett, in der Realität oft aber langsamer als PHP. .Net ist schon wieder so MS-lastig, mag ich aus Prinzip nicht und läuft nicht auf Linux-Maschienen.

    Nicht falsch verstehen, ich mag PHP absolut nicht. Ich habe bei einem Projekt für die Arbeit krampfhaft versucht Python zu verwenden, letztendlich ist das Ganze ins Wasser gefallen da die meiste Webtechnologie eben PHP ist ...und ich durfte und darf immer noch den Käse in PHP schreiben.



  • PHP ist nicht wirklich die schönste Sprache, darauf wollte ich aber nicht hinaus :)... Und ich habe keine Alternativen, daher muss ich auf diese Sprache zurückgreifen ;)...

    Aufgefallen ist nur:
    Bei der Erzeugung von einer bestimmten Anzahl von Objekt braucht das Script eine bestimmte Menge an Speicher. Will ich den Speicher mit unset von 50% der Objekte wieder "freigeben", sinkt zwar der Speicherverbrauch des Scripts auf 50% - aber der Interpreter braucht etwa um 10 - 20% länger. So hat man zwar mehr Speicher, aber das Script dauert länger - überschreitet man die Max-RAM-Usage nicht (bei meinen Testservern 128MB), ist diese Art der Optimierung also sinnlos, da das Script langsamer wird und der Interpreter am Ende des Scripts ohnehin sämtlichen Speicher wieder freigibt.


Anmelden zum Antworten