Speicher einer Instanz freigeben

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Speicher einer Instanz freigeben

    Hallo, ich wollte fragen, wie man in php ( 5 ) den Speicher einer Instanz friegeben kann, sprich wie ich eine Instanz wirklich destruieren kann.
    Der Grund ist, dass ich eine Schleife mit im Schnitt 6000, aber bis zu 18000 durchläufen habe.
    In dieser Schleife Instanziiere ich einen Controller.
    Diesen muss ich komplett neu bauen, da aus design Gründen keine setter
    vorhanden sind. Sprich dieses Objekt genau für diese Werte existiert, und alles nötige zu diesen erhält. Sprich alle attribute sind abhängig von den Konstruktionsparametern.
    Somit ist ein setter nichts anderes als ein C-tor, somit wär es ein hack und nichts weiter.
    Nachdem ich mal unset probiert habe, wusste ich eigentlich schon nicht weiter.

    Für die Vorstellung:

    PHP-Code:
    //ca 6000-18000 durchläufe
    foreach($this->addr_list_ as $addr_id){
        
    //laden aller informationen für den ctor aufruf 
        
    ctrl=new xxx_controller($name,$kid);//instanziierung
        //aktionen des controllers


  • #2
    Irgendwie verstehe ich dein Problem nicht.

    Auch nach 18000 mal "$var=new x();" existiert nur eine Variable, belegt nur einmal Speicher, denn der wird jedes Mal wieder überschrieben.

    Kommentar


    • #3
      existiert nur eine Variable, belegt nur einmal Speicher, denn der wird jedes Mal wieder überschrieben.
      Sollte man denken; ist aber ( in diesem Fall? ) nicht so,
      denn ich laufe out of memory.
      Mir ist natürlich klar, das ich mit dem namen ein neues objekt konstruiere.
      Der Speicher, den das ehemalige verbraucht hat, scheint aber intern noch nicht frei zu sein, auf jeden fall muss ich maximum memory auf mehr als 150mb
      stellen (zum testen , ob das auch das problem war), damit es zB 4000 mal durchläuft.
      Beispiel:
      Fatal error: Allowed memory size of 163577856 bytes exhausted (tried to
      allocate 32769 bytes) in [...]
      Naja die Klasse hat halt auch noch member die klassen sind und klassen konstruieren, aber die sollten ja mit der destruktion der klasse, deren attribut sie sind, auch destruiert werden.(hoffe ich)

      Vor lauter freude am Spaß hab ich hier mal ein minimal Beispiel:

      PHP-Code:
      ...
      includes
      ...

          
      $i=0;
          while(
      true){
              echo ++
      $i."\n";
              
      $core=new xxx_controller(params);
          } 
      Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 8192 bytes) in [...]
      Auch hier kommt es bei einer der memberklassen zu dem Fehler..
      naja immerhin hat der controller 2 datenbankwrapperinstanzen, sowie
      einen xmlrpc processor als attribute... aber wie gesagt wenn php mir den speicher wieder geben würde, dann wärs kein problem.
      Achja die db klassen wrappen pear::db, falls das wichtig ist.
      Ich meine Immerhin legt Pear ja statische objekte an, kann ja sein, dass die erhalten bleiben... muss ich mal checken, vll wisst ihr ja was dazu...
      Ansonsten hätte ich keine Ahnung warum das Programm sich so verhält.
      Zuletzt geändert von shapeless; 27.06.2006, 12:51.

      Kommentar


      • #4
        Ich kenne deinen Code nicht, aber wenn die Objekte nicht zerstört werden, dann scheint noch eine Referenz auf das Objekt zu existieren (RefCounter != 0).

        http://de3.php.net/manual/en/languag...asic.php#51396
        http://derickrethans.nl/files/phparc...es-article.pdf

        Kommentar


        • #5
          *ungetestet*
          PHP-Code:
          $i=0;      
          while(
          true)
          {          
             echo ++
          $i."\n";          
             
          $core=new xxx_controller(params);      
             
          // tuwas mit dem Objekt
             
             // zerstoeren
             
          $core NULL;
             unset(
          $core);

          Das sollte der PHP Müllabfuhr auf die Sprünge helfen...
          Zuletzt geändert von combie; 27.06.2006, 13:56.
          Wir werden alle sterben

          Kommentar


          • #6
            Original geschrieben von onemorenerd
            Ich kenne deinen Code nicht, aber wenn die Objekte nicht zerstört werden, dann scheint noch eine Referenz auf das Objekt zu existieren (RefCounter != 0).
            Naja doch du kennst Ihn:
            PHP-Code:
            <?php
            ...
            includes
            ...

                
            $i=0;
                while(
            true){
                    echo ++
            $i."\n";
                    
            $core=new xxx_controller(params);
                }
            ?>
            Das ist mein Minimalbeispiel.
            Die Klassen kennst du in der Tat nicht, aber die sind auch zu gross und verworren.
            Die klasse database ( member des controller ) ist auf jeden fall
            von PEAR:B abgeleitet. davon sind 2 instanzen jeweils attribut.
            der xmlrpc prozessor (auch member des controllers )
            benutzt die gleiche datenbankklasse (sprich hat auch eine instanz von ihr ).

            Was ich mich noch frage ist, sollte nicht wenn ein Schleifendurchlauf ist,
            sprich der Controller zerstört wird, so oder so alles zerstört werden,
            denn selbst wenn intern hin und her kopiert wurde und referenzen existieren,
            sind sie doch so oder so nur member der member, diese sollten doch
            dann eh alle mit destruiert werden, oder sehe ich das falsch?


            Danke für die Referenzinfos.. werd sie mir mal ansehen,
            aber die Frage wär halt noch zu klären.

            @combie

            Danke für den Vorschlag, NULL und unset in kombination hatte ich noch nicht
            verwendet, aber leider klappt auch das nicht...

            Zuletzt geändert von shapeless; 27.06.2006, 16:04.

            Kommentar


            • #7
              Gedanken:
              Die Objekte könnten in einer Kettenstruktur sein, z.B., aus irgendwelchen Gründen. Es hat in den UCN auch eine Memory Leak Beschreibung i Zsh mit Funktionen.

              Man könnte mal einen Destruktor einbauen und schauen, ob er aufgerufen wird..
              Es muss ja nicht ein Testlauf mit 6000 Objekten sein.

              Objekte können anscheinend nicht explizit zerstört werden, obwohl das Manual im Abschnitt __destruct dies erwähnt. Auch die User Contributed Notes erwähnen es nicht.

              Um ein objekt zu "zerstören" (somit den reference count vermindern) ist im Manual die Methode: $objekt= NULL; angegeben.

              edit: Es wäre interessant, mal einen Objekt-Baum anzulegen und dann die $Wurzel =NULL zu setzen - werden dann die destructors der Nachfahren aufgerufen? siehe übernächster Beitrag.
              Zuletzt geändert von tcpip; 27.06.2006, 15:42.

              Kommentar


              • #8
                Rekursive bzw. zirkuläre Referenzen werden nicht entdeckt.
                bug report 33595 ist open.
                weiterer bug report in diesem Zusammenhang 33487, vermutlich dasselbe aber unklar.
                UCN http://de3.php.net/manual/en/languag...econ.php#59272 gibt eine Einfache Situation.

                Umgehungsmöglichkeiten habe ich keine beschrieben gesehen.

                Der Effekt "braucht rasch sehr viel Speicher" wird genau so beschrieben in 33595 und fast gleich in 33487.

                der .pdf Artikel ist über Objekte und reference counting in php4.3 hier geht es aber um php5.
                Zuletzt geändert von tcpip; 27.06.2006, 15:13.

                Kommentar


                • #9
                  Die "sandbox" sagt, dass zyklische Referenzen nicht 'entdeckt' werden.

                  Ein Baum mit nur aufwärts-Referenzen funktioniert, dh. mit $wurzel=NULL wird der ganze Baum sofort gelöscht.

                  Ein Baum mit aufwärts- und abwärts-Referenzen funktioniert nicht, dh mit $wurzel=NULL wird kein Objekt des Baums gelöscht. Es wird alles erst am Schluss des Skripts gelöscht.

                  Umfang der Sandbox: 40 Zeilen.

                  Kommentar


                  • #10
                    Danke :thumb up:

                    Ich denke die Überlegungen gehen in die richtige Richtung. ich werde das Ganze
                    mal ein wenig nachvollziehen und der Sache noch ein wenig folgen.

                    zur Destruktorfrage: wenn ich __destruct einbaue, wird der destruktor nicht
                    bei jeden durchlauf aufgerufen,sondern, wie du es bei den ringverknüpften bäumen beschrieben hast, am ende des Scriptes.
                    Ausgabe:
                    [....]
                    250
                    251
                    252
                    253
                    254
                    255
                    256

                    Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 8192 bytes) in /usr/local/omc/lib/libdb/db_iface.php on line 67
                    japp destructed
                    japp destructed
                    japp destructed
                    japp destructed
                    japp destructed
                    [...]
                    Naja, dann scheine ich mich wohl drum kümmern zu müssen, ob es ring-referenzen gibt... Naja, mal sehen ob sich der Aufwand lohnt..
                    Danke auf jeden Fall.

                    Kommentar


                    • #11
                      Es muss nicht ein ring sein. eine Vater-Sohn Verknüpfung in beide Richtungen reicht völlig aus. Das ist sogar sehr vernünftig, z.B. hat das DOM jedes element auch alle childs und den parent.

                      Anlässlich des Löschens eines Objekts müsste man auch den parent-Link ausNULLen, und allen 'childs' einen Good-Bye-Kuss senden, anstatt sie bloss auszuNULLen).

                      Kommentar


                      • #12
                        Japp, das stimmt.
                        Ich meinte mit Ringreferenz auch nicht zwingend eine ads mit Ringausshen,
                        sondern auch 2 Baumknoten die gegenseitig verknüpft sind.
                        ( sprich einen ring durch ihre verbindungen bilden)
                        War vll etwas ungenau formuliert.. naja dann muss ich wie gesagt noch schauen, ob die suche und der Aufwand zu rechtfertigen ist.

                        thx

                        Kommentar


                        • #13
                          Sorry für das vorangehende, in dem Fall.

                          Der gleiche Fehler ist ja wohl auch in einer "gewöhnlichen" Anwendung (nur hat diese viel weniger Objekte,) sodass es aus den verwendeten PEAR und DB-includes nicht zu eliminieren ist. Ausser es sei von Dir eingebaut, dann wirst Du es rasch finden.

                          Ich nehme auch weniger an, dass dein Skript eine human HTML-Ausgabe produziert deshalb: Kannst Du es splitten und zusammensetzen? z.B. mit header (Location: http://$host.$php_self?split=nn) den nächsten php-Split auslösen, mit ob_ die Teilergebnisse zwischenspeichern?

                          Kommentar

                          Lädt...
                          X