Andreas Dölling: Performance-Verlust durch OOP?

Hallo,

ich habe ein kleines Prototyp-Script, das mit einzelnen Funktionen im globalen Namensraum arbeitet, nachträglich in eine Klasse gekapselt.
Die Funktionalität an sich blieb dabei unverändert, außer daß natürlich z.B. aus globalen Variablen Objekteigenschaften wurden.

Das Ganze funktioniert auch - allerdings mit einer Performance-Einbuße, die sich gewaschen hat.
Während das prozedurale Prototyp-Script für eine Beispielaufgabe 1,4 Sekunden benötigt, braucht die entsprechende Methode der Klasse satte 36 Sekunden!

Ich kann mir das absolut nicht erklären.

Zur Info:
Es handelt sich um ein Script, das mit domxml_open_file() eine HTML-Datei einliest und sich aus dem DOM-Baum das Element mit der ID "content" holt.
Dieses Element und seine Kinder werden nun rekursiv durchlaufen. Textknoten in bestimmten Elementen (P, TD, DIV, SPAN) werden nach Glossarbegriffen durchsucht. Gefundene Begriffe werden durch entsprechende DFN-Elemente ersetzt.
Der Performance-Verlust tritt in der rekursiven Funktion auf, also der Kernfunktion.

Die Aufgabenstellung entspricht weitgehend der aus dem JS-Strang http://forum.de.selfhtml.org/archiv/2005/2/t100676/#m617171.
Damals wurde mir geraten, das Ganze serverseitig mit PHP und dessen XML-Extension zu lösen, um die Javascript-Performance-Probleme zu umgehen.

Tja, jetzt stehe ich wieder vor dem alten Problem.

Ich könnte nun natürlich einfach die prozedurale Lösung, also den Prototypen, verwenden, der ja befriedigend schnell läuft.
Aber ich möchte das Ganze gerne kapseln. Und vor allem möchte ich wissen, WARUM das Script in der OOP-Version plötzlich so elend langsam ist.

Wäre für Hinweise sehr dankbar.

Der Code ist recht umfangreich. Kann ihn aber bei Interesse gerne posten.

Thanx,
Andreas

  1. Habe soeben diesen Link gefunden: http://www.webmasterstop.com/56.html.
    Ein Performance-Vergleich mit PHP (Klassen - Funktionen - prozedural).

    Das nur als Randnotiz.

    Ciao,
    Andreas

    1. Huhu Andreas

      Habe soeben diesen Link gefunden: http://www.webmasterstop.com/56.html.
      Ein Performance-Vergleich mit PHP (Klassen - Funktionen - prozedural).

      Das nur als Randnotiz.

      Mmmmh, der Test ist aber unfair.

      for ($i=0; $i<1000000; $i++)
      {
            $testclass=new test();
            $cnt+=$testclass->one();

      }

      Der legt bei jedem Schleifendurchgang eine neue Objekt-Instanz an.

      Richtigerweise müsste das wohl eher so aussehen:

      $testclass=new test();
      for ($i=0; $i<1000000; $i++)
      {
            $cnt+=$testclass->one();

      }

      Dann sollte der Unterschied zwischen OOP und PP auch nicht mehr so gravierend sein.

      Viele Grüße

      lulu

      --
      bythewaythewebsuxgoofflineandenjoytheday
    2. was für eine schwachsinniger vergleich was der da macht..
      der hätte ja gleich drei objekte in einem initialisieren können.

      das wäre genauso effektiv gewesen *kopfschüttel*
      wurde das evtl. von mic... finaziert? *löl*

  2. Hi!

    Prinzipiell erzeugt OOP natürlich Overhead, wenn man es aber geschickt anwendet, kann es durchaus auch vorteilhaft sein:
    http://www.sitepoint.com/blog-post-view.php?id=223760
    http://www.sitepoint.com/blog-post-view.php?id=224444

    Nach Möglichkeit solltest Du Referenzen verwenden. Da ich das Script nicht kenne kann ich auch nichst zum Problem sagen, aber vermutlich hat es damti zu tun dass Du durch die etwas "bwschränkte" OOP in PHP4 ständig Objekte/Daten "rumkopierst", anstatt mit Referenzen auf die Daten zu arbeiten. Es kann z.B. gut sein dass Dein Scriupt mit PHP5 _erheblich_ schneller wird. Wenn Du kein PHP5 verwenden kannst, musst Du eben manuell dafür sorgen dass Objekte wo immer möglich per Referenz übergeben werden.

    Es handelt sich um ein Script, das mit domxml_open_file() eine HTML-Datei einliest und sich aus dem DOM-Baum das Element mit der ID "content" holt.

    Die domxml Extension ist nie über einen experimentellen Status hinausgekommen, und wird es auch in Zukunft nicht mehr, da es für PHP5 bereits eine vollständig überarbeite DOM-Extension gibt. Das solltest Du evtl. berücksichtigen.

    Dieses Element und seine Kinder werden nun rekursiv durchlaufen.
    Textknoten in bestimmten Elementen (P, TD, DIV, SPAN) werden nach Glossarbegriffen durchsucht. Gefundene Begriffe werden durch entsprechende DFN-Elemente ersetzt.

    Wieso musst Du das unbedingt so aufwändig parsen? Könntest Du die Ersetzungen nicht direkt im String vornehmen?

    Aber ich möchte das Ganze gerne kapseln. Und vor allem möchte ich wissen, WARUM das Script in der OOP-Version plötzlich so elend langsam ist.

    Wäre für Hinweise sehr dankbar.

    schlecht zu sagen ohne Code ;-)

    Der Code ist recht umfangreich. Kann ihn aber bei Interesse gerne posten.

    Wenn es etwas mehr Code ist am besten hochladen (als .phps oder sowas), oder sonst, wenn das nicht möglich ist sowas verwenden: http://rafb.net/paste/

    Grüße
    Andreas

    PS: Interessant ist auch das folgende Posting von Kristian Köhntopp: http://www.php4-forum.de/forum.php3?nr=172421&site=0

    --
    SELFHTML Feature Artikel: http://aktuell.de.selfhtml.org/artikel/
    1. Hallo Andreas,

      Nach Möglichkeit solltest Du Referenzen verwenden. Da ich das Script nicht kenne kann ich auch nichst zum Problem sagen, aber vermutlich hat es damti zu tun dass Du durch die etwas "bwschränkte" OOP in PHP4 ständig Objekte/Daten "rumkopierst", anstatt mit Referenzen auf die Daten zu arbeiten.

      DAS war esd. Du hattest vollkommen recht mit Deiner Vermutung: ich hatte den zu bearbeitenden DOM-Knoten an die rekursive Methode immer by value und nicht by reference übergeben.
      Ich habe das jetzt geändert - und siehe da: das Script läuft jetzt in Normalzeit!

      Die domxml Extension ist nie über einen experimentellen Status hinausgekommen, und wird es auch in Zukunft nicht mehr, da es für PHP5 bereits eine vollständig überarbeite DOM-Extension gibt. Das solltest Du evtl. berücksichtigen.

      Leider ist auf den Servern, für die ich programmiere, nur PHP4 installiert.
      :(

      Aber es läuft ja jetzt!

      Danke Dir und den anderen!!!

      Ciao,
      Andreas

  3. Hallo Andreas,

    also ich bin mir ziemlich sicher, dass das nicht der normale Overhead ist, irgendetwas hast Du auf eine sehr ungeschickte Art gelöst.
    Die Aufgabe klingt für mich aber so, dass ich hierfür XPath Funktionen und eventuell XSL Transformationen einsetzen würde. Damit geht wahrscheinlich alles viel einfacher.
    Dafür solltest Du dann aber wirklich PHP5 nehmen.

    Gruss

    Marko

    1. Hi Marko,

      also ich bin mir ziemlich sicher, dass das nicht der normale Overhead ist, irgendetwas hast Du auf eine sehr ungeschickte Art gelöst.

      Wahrscheinlich, denn ich habe bis jetzt keinen stichhaltigen Hinweis im Netz gefunden, der belegt, daß OOP in PHP dermaßen unperformant wäre.

      Die Aufgabe klingt für mich aber so, dass ich hierfür XPath Funktionen und eventuell XSL Transformationen einsetzen würde. Damit geht wahrscheinlich alles viel einfacher.

      Das mag sein - aber ich frage mich ganz einfach, warum das Ganze ohne die Kapselung in eine Klasse problemlos läuft.

      Ich poste gleich mal den Quellcode.

      Ciao,
      Andreas