Ankündigung

Einklappen
Keine Ankündigung bisher.

PHP Objekte Performance

Einklappen

Neue Werbung 2019

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

  • #16
    Zitat von Ulfikado Beitrag anzeigen
    OOP heist ja nicht ausschließlich im Kontext einer Instanz!
    Naja eigentlich schon. Mit Static wechselst du aus dem Instanzkontext in den Globalen Kontext, also arbeitest du nicht mehr mit Objekten sondern mit Strukturen bzw. Funktionen. So kannst du z.B. bei so gut wie allen OO-Sprachen nicht auf Overloading zurückgreifen.

    Zitat von Ulfikado Beitrag anzeigen
    Wenn static von Klassen (Methoden|Eigenschaften) verwendet wird ist es sehr wohl im Kontext der Klasse und nicht auf Funktionaler ebene.
    In PHP könntest du z.B. auch mit globalen Funktionen arbeiten um static zu ersetzen. In Java oder C# hast du allerdings nicht die Möglichkeit mit Funktionen zu arbeiten. Deshalb u.a. static.
    Bei Java z.B. hast du die Klasse Math, die besteht nur aus static Methoden. Zwischen den einzelnen Methoden besteht keinerlei konzeptioneller Zusammenhang und wurden nur thematisch in eine Klasse zusammengefasst. Ob das jetzt Funktionen wären (wenn es die in Java geben würde) oder eben Methoden macht keinen Unterschied
    "Software is like Sex, it's best if it's free." - Linus Torvalds

    Kommentar


    • #17
      Moni86

      Ich halte es für eine schwierige Sache, den Gedanken "Die Performance muss stimmen" direkt mit dem Objektmodell von PHP in Zusammenhang zu bringen. PHP (insbesondere die neueren Versionen) verwaltet Objekte einigermaßen effizient und solange du nicht Unmengen von Objekten generierst, wird das wahrscheinlich nicht der Performance-Flaschenhals deiner Anwendung sein.

      Einige Grundregeln, die aus meiner Sicht Sinn machen, um die Performance positiv zu beeinflussen:

      Die Datenbank gut konfigurieren
      Indizes und gut gewählte Datentypen in der Datenbank, eine gute Partionierung und Einrichtung des DBMS vermeiden Performanceprobleme von Grund auf. Schlecht konfigurierte Datenbanken sind eine häufige Problemursache.

      Prepared Statements verwenden
      Prepared Statements sind nicht nur aus Sicherheitsgründen empfehlenswert, sondern verbessern auch die Performance, weil der Ausführungsplan in der Datenbank nur einmal erstellt werden muss. Somit wird bei jedem SQL-Query, der schon in ähnlicher Form ausgeführt wurde und bei dem sich nur einige Werte ändern, Zeit eingespart.

      Lass die Datenbank die Arbeit machen, wo es geht
      500000 Datenbankeinträge zu laden, um in PHP einen Durchschnitt auszurechnen, macht keinen Sinn. Kann man auch mit Datenbankfunktionen erledigen. Man sollte sich also besonders bei Aufwändigen PHP-Bausteinen fragen: Kann ich das auch die Datenbank machen lassen?

      Nicht zu viele Daten auf einmal laden
      Bei jedem Request einen Join auf 6 Tabellen zu machen, damit in einer Tooltip-Ansicht auch die Berechtigungen und Rollen des angemeldeten Benutzers angezeigt werden, macht wenig Sinn. Hier sollte man sich überlegen, ob man diese Infos alle auf einmal braucht, oder ob es nicht klüger wäre, einzelne Datensätze per Klick und Ajax nachzuladen. Wahlweise könnte man auch Caching verwenden.

      Caching sinnvoll einsetzen
      Aufwändige Berechnungen und lange andauernde Programmteile sollte man Cachen, wenn sich die Daten nicht all zu oft ändern. Hier empfiehlt es sich, sich auch mal mit den HTTP-Caching-Headern auseinander zu setzen (304 not modified, IF-MODIFIED-SINCE, pragma, cache-control, etag, last-modified, etc.). Oft muss man PHP gar nicht anwerfen sondern kann das schon auf Webserver-Ebene behandeln. Der kann nämlich meistens auch Multithreading und ist deutlich schneller als PHP.

      Session nicht als Datencache misbrauchen
      Viele PHP-Programmierer nutzen die Session als Daten-Cache für alle möglichen Infos (Benutzerdaten, Konfigurationsdaten, etc.). Das ist keine gute Idee, denn die Session ist häufig ein sehr langsamer Speicher, der bei jedem Request für jeden User geschrieben und gelesen werden muss und der dazu führt, dass PHP für andere Requests blockiert wird (sehr schlecht für parallele Ajax Requests)... mehr dazu hier: http://phpchunk.net/2011/06/speed-up...est-practices/

      Autoloader optimieren
      Composer ist DAS Werkzeug für PHP, um Abhängigkeiten effizient zu verwalten. Er verfügt auch über einen guten Autoloader. Leider wird dieser nur selten so konfiguriert, dass die Autoload-Files optimiert werden. Das macht ganz schön was aus. Mehr dazu hier: https://getcomposer.org/doc/03-cli.md#dump-autoload

      Das hier in der composer.json auf oberster Ebene ist schon ganz nett:
      Code:
      "config": {
              "optimize-autoloader": true
       }

      Performance Probleme nicht vermuten, sondern verifizieren
      Häufig vermutet man Performance-Probleme, wo keine sind. Verifizieren kann man das z.B. mit der xdebug extension. Dort kann man einen Profiler aktivieren, der einem relativ genau sagt, in welchen Programmteilen bei PHP die meiste Zeit verbracht wird. Ohne so ein Werkzeug, ist es schwierig bis unmöglich, Problemen auf die Spur zu kommen. Zur Analyse der Dateien, die da rausfallen (cachegrind...), kann man für Windows z.B. qcachegrind verwenden. PHPStorm kann das aber auch (Tools, Analyse XDebug Profiler Snapshot)

      Wenn du die beste Performance willst und das dein Hauptaugenmerk ist (nicht einfache Entwicklung, Kompatibilität zu vielen Webhostern, große Community, etc.), dann ist PHP wahrscheinlich nicht die allerbeste Wahl, aber in den meisten Fällen kriegt man bei guter Pflege auch große Anwendungen mit PHP flott
      Tutorials zum Thema Technik:
      https://pilabor.com
      https://www.fynder.de

      Kommentar


      • #18
        Lieber Andreas,

        vielen lieben Dank für Deine Mühen und wirklich ausführlich Antwort, das ist eine gute Hilfe!
        Ich hätte z.B. immer gedacht die Datenbank so wenig wie möglich zu belasten statt die Datenbank Funktionen zu nutzen. Ist bestimm je nach Abfrage und Anforderung auch abhänging. Sehr nützliche Tipps - vielen Dank. Ich werde jeden einzelnen durcharbeiten.

        Ich bin halt neu in der OOP. Mir fehlt halt noch etwas das Gefühl für Objekte und wie man diese am sinnvollsten handhabt.

        Es gibt ja die Funktion __destruct() die angeblich überflüssig sein soll da PHP selber nach Beendung das vornimmt (Garbage Collection). So liest man es. Beendung wäre für mich wenn ich die Seite schließe. HTTP ist ja zustandslos, dann müsste doch eigentlich sofort bei jedem Request Object nicht gespeichert werden außer ich verweise z.B. mit einer Session drauf?! Denke ich da richtig?

        Ich meine, bei prozedualem PHP schicke ich meine Anfrage - der Server/PHP bearbeitet es und schickt fertige Seite zurück. Danach weiß er von mir nichts mehr. Dafür ja alternativ dann die Sessions. Hier wäre für mich jetzt eine Punkt wo man Performance einbüßen könnte - WIE AUCH DU OBEN BEREITS ANGESPROCHEN HAST.

        Also hier am besten kein kompletten Object speichern um die Daten gleich wieder parat zu haben, sondern lediglich einzelne Werte (z.B. eine ID?) womit man entsprechend dann sich die Daten/Objekte aus der Datenbank bei Bedarf holt? War das so gemein? Somit hätte ich auch kein Verweis auf mein Objekt mehr und es würde nach dem Request auch wieder weg?

        Vom Prinzip wie beim MVC den Controller immer recht schlank halten.

        Dann kommt natürlich das beliebte Singleton Hier bleibt ja die Instance statisch bestehen. Das soll gut für eine Datenbank-Verbindung sein, da "immer eine neu Verbindung aufzubauen Performance kostet und man ja nur eine braucht.." So habe ich es oft gelesen. Macht diese Aussage Sinn, ist das so? Ohne Singleton, prozedural stellt man seine Verbindung her, übermittelt den Request, wertet aus und schließt die mit close($verbindung) wieder wobei man den Befehl wohl weglassen kann?!. So bei MySQli zumindest. PDO muss ich mich noch mehr mit beschäftigen. Aber auch bei WordPress soll man den eigenen Querie nach seiner Abfrage / Verbindung wieder freigeben/bereinigen. Wie sollte man es hier am besten objektorientiert handhaben? Ist für MySQL besser einer Verbindung/Instance immer offen für alle zu haben oder lieber lieber mit der Abfrage sich verbinden?

        Static wurde hier etwas aus OOP Sicht kritisiert aber ich habe es bei so vielen Pattern gesehen.

        Es wurde auch hier etwas über das Singleton und Registry Pattern geschrieben und das Dependency Injection lieber zu nutzen sei. Jetzt habe ich folgendendes gelesen:
        The registry pattern also makes the dependency injection easier, as instead of making the object, or the object it contains globally available - for example, through being a Singleton.

        Ich hatte immer gedacht, das durch namespaces und DI das Regsitry überflüssig sei? Aber ich bin ja noch ganz am Anfang. Wie siehst Du / ihr das?

        Wenn du die beste Performance willst und das dein Hauptaugenmerk ist (nicht einfache Entwicklung, Kompatibilität zu vielen Webhostern, große Community, etc.), dann ist PHP wahrscheinlich nicht die allerbeste Wahl, aber in den meisten Fällen kriegt man bei guter Pflege auch große Anwendungen mit PHP flott
        Nur interessehalber, welche Sprache hättest du bevorzugt?

        Auch allen anderen vielen Dank für die geschriebenen Antworten.


        Liebe Grüße
        Moni

        Kommentar


        • #19
          Wie du richtig erkannt hast, hat PHP einen Garbage Collector. Der wird aufgerufen, falls du es möchtest, am Ende einer Funktion/Methode und am Ende der Ausführung. In PHP arbeitet man eigentlich nur mit Requests, d.h. der Livecycle einer PHP-Anwendung bezieht sich nur auf einen einzelnen Request. Dementsprechend sollte man dann auch denken wenn man die Anwendung entwickelt. Destruktoren gibt es in PHP, da man Entwicklern die Möglichkeit geben will, zu entscheiden was passiert wenn ein Objekt zerstört wird. Da kann man dann z.B. Daten noch speichern oder andere Aktionen starten. Für PHP meistens nicht ganz so relevant, in C++ aber z.B. kommt ihm viel Bedeutung zu, da dort z.B. der Speicher wieder freigegeben werden kann etc.
          Mit Sessions kannst du Daten über mehrere Requests hinweg behalten. Aber für komplette Objekte etc. ist die Session definitiv nicht gedacht, macht bei einem Request Object ja auch kein Sinn, da ein Request Objekt ja immer vom aktuellen Request abhängt oder?

          Daten sollten in einer Datenbank immer atomar vorliegen, was nicht mehr der Fall ist, wenn du z.B. Objekte in der Datenbank speicherst. Wie du das schon richtig gesagt hast, ist da eher schon der richtige Weg, ID's in der Session zu speichern und anhand dieser wieder die Daten aus der Datenbank laden und Objekte daraus zu generieren. Du solltest da vorallem auch an den Fall denken, dass deine Anwendung nicht immer die gleiche Struktur haben wird wie sie in der Datenbank repräsentiert wird. Deshalb ist es auch eine ganz schlechte Idee Objekte in der Datenbank zu speichern. Die Anwendung muss wissen wie sie aus den Daten Objekte generiert.

          Zum Thema Singleton:

          Was meinst du damit, dass die Instanz statisch bestehen bleibt? Meinst du, dass das Objekt in einer statischen Klassenvariable liegt?
          Wie du schon richtig erkannt hast, sind Datenbankverbindungen ÖFTERS Singleton. Allerdings bei weitem nicht immer. Bei größeren Anwendungen oder bei unterschiedlichen Anwendungsfällen hast du auch mehrere Datenbankverbindungen die du verwalten musst. Ein Singleton ist da natürlich komplett falsch. Aber oft geht mit der Datenbank auch nur eine Instanz her, da nur eine Verbindung.
          Wenn du mit einer Datenbankklasse arbeitest, steht jedes Objekt für eine Datenbankverbindung. In der Regel ist diese Verbindung solange geöffnet bis du sie nicht mehr brauchst (also meistens vom Anfang bis zum Ende der Ausführung).
          Bei Mysqli sollte ebenfalls die Datenbankverbindung geschlossen werden, dort wird das mit der Methode close() gemacht.

          Was meinst du mit Query freigeben?
          Freigeben musst du da eigentlich gar nichts, außer vllt. das Result Objekt zu leeren/löschen (wobei das normalerweise sowieso überschrieben wird).

          Wie du solch eine Datenbankklasse am Besten gestaltest, solltest du vllt. anhand einer Beispiele nachschauen. MySQLi ist ja schon Objektorientiert, an sich brauchst du da gar nicht mehr so viel.
          Wie ich schon gesagt habe, am Besten ist es eine Datenbankverbindung über die komplette Anwendungslaufzeit offen zu halten und am Ende wieder abzubauen (close()).


          Namespaces und DI haben in erster Linie nichts miteinander zu tun.
          Das Registry Pattern ist für die globale Verfügbarkeit von Variablen außerhalb dem globalen Kontext erdacht worden. Das findet meistens in DependencyInjection Containern einsatz (zur verwaltung der Objekte).
          Über das Thema kannst du dir z.B. einen Artikel von Fabien Potencier (Symfony2) durchlesen: http://fabien.potencier.org/what-is-...injection.html
          Das Thema ist etwas komplexer als es nur hier in einem Post anzureißen, und man sollte sich schon näher damit beschäftigen.


          Zum Thema Geschwindigkeit:

          PHP wurde speziell für Webanwendungen entwickelt. PHP ist nicht die schnellste Sprache, was u.a. daran liegt dass es interpretiert wird etc.
          Allerdings hat sich mit PHP 7 sehr viel geändert, sodass PHP nun wirklich sehr sehr schnell geworden ist und der Aspekt mit der Geschwindikeit m.E. nach nicht mehr zieht.
          Natürlich kann man auch mit Assembler seine Anwendungen schreiben, dürfte wohl am schnellsten sein


          Wie schon gesagt wurde, mach dir wegen der Geschwindigkeit nicht sooo große Gedanken. Objekte zu initialisieren etc. dauert alles nicht so lange. Lange Ladezeiten hast du vorallem wegen vielen Datenbankabfragen o.ä.
          Wenn du richtig Geschwindigkeit einsparen möchtest, kannst du z.B. sehr viel an den Client auslagern und PHP nur noch als Datenquelle nutzen.

          Ich hoffe ich konnte dir etwas helfen.

          Gruß
          Jama
          "Software is like Sex, it's best if it's free." - Linus Torvalds

          Kommentar


          • #20
            Ich hätte z.B. immer gedacht die Datenbank so wenig wie möglich zu belasten statt die Datenbank Funktionen zu nutzen.
            Datenbanken sind ein eigenes Thema... meiner Erfahrung nach kommt es in 8 von 10 Fällen wegen langsamer oder schlecht formulierter Datenbankabfragen oder falscher Konfiguration zu Problemen. Warum ich das Thema Datenbanken so fokussiert habe, ist, weil Datenbanken im Allgemeinen sehr effizient mit CPU-Zeit umgehen. Die besten Daten sind Daten, die erst gar nicht geladen und übertragen werden müssen. Holst du also viele Daten von der Datenbank ab, sparst du zwar etwas CPU-Zeit bei der Datenbank, aber PHP muss viel mehr arbeiten. Und da PHP in der Regel langsamer arbeitet als eine in hardwarenahem Code implementierte Datenbank-Engine, ist es oft sinnvoll, genau darüber nachzudenken, was du die Datenbank machen lässt. Das heißt natürlich nicht, das generell ALLES besser in der Datenbank aufgehoben ist. Ich denke, meine Aussage ist aber nun klar.


            Denke ich da richtig?
            Daten bleiben nicht über Requests bestehen, es sei denn, du persistierst / speicherst sie. Als Speicher kann man verschiedene Sachen verwenden. Dateien, Datenbanken, die Session oder auch Caches. Was in welchem Fall der richtige Speicher ist, entscheidest nur du... Ich persönlich nutze sehr gerne Caches (z.B. Memcache oder APC) und Datenbanken (schnell) und sehr ungern Dateien und Sessions (langsam). Hier gilt es, den richtigen Kompromiss zwischen Bequemlichkeit und Performance zu finden... Sessions und Dateien sind bequem, aber langsam, Datenbanken und Caches etwas komplexer, aber schnell.

            Also hier am besten kein kompletten Object speichern um die Daten gleich wieder parat zu haben, sondern lediglich einzelne Werte (z.B. eine ID?) womit man entsprechend dann sich die Daten/Objekte aus der Datenbank bei Bedarf holt?
            Ja, genau so. Noch besser als Datenbank wäre ein Cache, der beim Ablauf der Session invalidiert wird. Dann spart man sich einen Haufen Datenbank abfragen. Sehr schön sind auch Fallback-Mechanismen. Z.B.:
            1.) Prüfe den Cache, falls vorhanden, lade aus Cache
            2.) Falls nicht vorhanden, lade aus Datenbank und schreibe den Cache

            Dann kommt natürlich das beliebte Singleton
            Singletons sind nicht wegen der Performance doof. Im Wesentlichen lassen sich Singletons einfach schwierig testen bzw. mocken (Unit-Tests / PHPUnit solltest du dir unbedingt anschauen) und führen durch starke Kopplung und verzweigte Abhängigkeiten oft zu unstrukturiertem und schwer wartbaren Code. Sie zwangsläufig als schlecht zu bezeichnen halte ich für eine schwierige Aussage... Auch wenn ich es aufgrund besserer Mechanismen nicht mehr gerne verwende, ist der Begriff Anti-Pattern sehr reißerisch.

            Aber auch bei WordPress soll man den eigenen Querie nach seiner Abfrage / Verbindung wieder freigeben/bereinigen. Wie sollte man es hier am besten objektorientiert handhaben? Ist für MySQL besser einer Verbindung/Instance immer offen für alle zu haben oder lieber lieber mit der Abfrage sich verbinden?
            Damit ist was anderes gemeint. Wenn du eine Datenbankabfrage mit vielen Ergebnissen hast, bleiben diese im Speicher. Wenn du weißt, dass du die Ergebnisse nicht mehr brauchst, gibst du den Speicher wieder frei. Bei PDO kannst du das mit closeCursor machen... Eine Datenbankverbindung selbst sollte pro Request nur einmal aufgebaut werden... kann aber auch sein, dass man mehrere braucht, z.B. wenn man eine MySQL-Datenbank mit einer SQL Server Datenbank synchronisieren will. Dann baut man aber möglichst jede Verbindung nur einmal auf, denn der Verbindungsaufbau kostet Zeit... es gibt sogar persistente Verbindungen (Request-Übergreifend), aber davon würde ich gerade als Anfänger die Finger lassen.
            Kurzfassung: Datenbankverbindung nur einmal aufbauen, nicht pro Query, und nach jedem Query das Query-Resultset mit closeCursor freigeben, wenn man es nicht mehr braucht.

            Nur interessehalber, welche Sprache hättest du bevorzugt?
            Ich bevorzuge PHP. Aber mir ist Performance auch nicht das wichtigste, sondern die benötigte Entwicklungszeit bei immer noch schneller Performance. Mit PHP kann man, wenn man es beherrscht, sehr schnell Web-Anwendungen entwickeln und liegt schon lange in der Sonne, während man mit anderen Sprachen noch nicht halb fertig ist. Performancekritische Anwendungen würde ich vermutlich in C / C++ schreiben (hardwarenah). Aber in die Situation, dass PHP zu langsam für eine Web-Anwendung war, bin ich noch nie gekommen.

            Noch ein Tipp: Löse dich mal von der Theorie und spring einfach ins kalte Wasser. Programmieren lernt man nicht, in dem man drüber liest oder diskutiert. Auch wenn es interessant ist, all diese Dinge vorab mal zu besprechen, verlass dich einfach mal drauf, dass viele Dinge einfach erstmal gemacht werden müssen, bevor man sie versteht. Selbst in wirklich tollen Frameworks ist bei weitem nicht alles perfekt gelöst. Aber von Frameworks kann man oft viel lernen, schau dir bezüglich Dependency Injection mal den Code von Symfony an. Dort macht man viel richtig. Aber sieh es bitte nicht als Non-Plus-Ultra
            Tutorials zum Thema Technik:
            https://pilabor.com
            https://www.fynder.de

            Kommentar


            • #21
              Guten Morgen Jama und Andreas,
              ihr habt wirklich all meine Fragen beantwortet und das, sehr verständlich. Ich kann mich nur recht herzlich für diese Hilfe bedanken
              Ich denke auch, das ich jetzt erst einmal weiter meine Schwimmübungen machen werde Das macht schon Sinn.

              Ich freue mich sehr, das hier so eine gute und nette Community ist. Da macht das auch schon gleich mehr Spaß.

              Sollte ich was erleben und es hier passen, berichte ich meine Erfahrung auch gerne.

              Habt einen schönen Tag.

              Viele Grüße
              Moni

              Kommentar

              Lädt...
              X