MB: warum nicht selbst cachen

moin,

welche Aspekte bei BuiltIn-Funktionen bezüglich cachen machen im Kontrast selbst cachen überflüssig?

  • Ein Aspekt mag wohl sein aus Performance-Gründen

aber mehr kann ich da wirklich nicht finden. Zum einleitenden Thread: permanenter Zugriff auf Daten aus Datenbank?.

kann man das nicht per signifikanten User Token von der $_SESSION-gesteuert selber cachen?

class Cache {
  
  private static $_token;

  public static function init( string $token ) {
    self::$_token = $token;
  }

  public static function store( array $data ) : bool {
    // schreibt die temporären daten serialisiert mit self::$_token in PATH Konstante
  }

  public static function load() : array {
    // prüft ob PATH Konstante existiert und der self::$_token angehängt ist
    // dann öffnet und deserialöisiert die Klasse den Content und gibt ihn als array zurüch
  }
}

lgmb

  1. Natürlich kannst Du Rückgabewerte von Funktionen cachen. Daß der Cache statisch sein muss hast Du ja schon richtig erkannt. So kannst den cache auch in der Funktion selbst deklarieren:

    echo mal2(2), "\n", mal2(2), "\n", mal2(2), "\n", mal2(3);
    
    function mal2($x){
        static $cache = array ();
        if( isset($cache[$x]) ){
            print "hit!\n";
            return $cache[$x];
        }
        else{
            $cache[$x] = 2*$x;
            return $cache[$x];
        }
    }
    

    Nur als Beispiel um das Prinzip zu zeigen. Kann praktisch noch viel mehr machen und auch DB Abfragen bzw. deren Ergebnisse cachen.

    MfG

    PS: In Perl gibts ein Modul Memoize da wäre nur der Name der Funktion zu übergeben und schon wird gecached, auch mit Builtinfunktionen. Vielleicht gibt ja sowas auch für PHP?

    1. Tach!

      Natürlich kannst Du Rückgabewerte von Funktionen cachen.

      Nur während des Requests. Ein PHP-Script hat keine requestübergreifende Lebensdauer. Das ist also kein Cache, sondern kann nichts, was eine einfache Variable nicht auch kann.

      PS: In Perl gibts ein Modul Memoize da wäre nur der Name der Funktion zu übergeben und schon wird gecached, auch mit Builtinfunktionen. Vielleicht gibt ja sowas auch für PHP?

      Nicht dass ich wüsste (und zum Standardlieferumfang gehört). PHP kennt erstmal nur Sessions als dauerhaften Speicher abseits von Dateien oder DBMS. Man kann sich aber selbst einen Session-Handler schreiben, der die Daten beispielsweise im Memcached statt in Dateien ablegt.

      dedlfix.

      1. @dedlfix

        Natürlich kannst Du Rückgabewerte von Funktionen cachen.

        Nur während des Requests. Ein PHP-Script hat keine requestübergreifende Lebensdauer.

        Schon falsch. Überlegst Du eigentlich bevor Du meine Posts kommentierst!?

        MfG

        1. Tach!

          Natürlich kannst Du Rückgabewerte von Funktionen cachen.

          Nur während des Requests. Ein PHP-Script hat keine requestübergreifende Lebensdauer.

          Schon falsch. Überlegst Du eigentlich bevor Du meine Posts kommentierst!?

          Lieber überheblicher pl, kläre mich doch bitte auf, was daran falsch ist, oder warum deine Aussage richtig sein soll, beziehungsweise wie man sie zu deuten hat, um sie richtig zu verstehen.

          dedlfix.

  2. Ja, warum willst Du nur die Ergebnisse der Bemühungen der Datenbank (die übrigens auch schon einen Cache hat) cachen und nicht gleich den kompletten Output? Den kann man sogar schon vorzippen und so den Server gehörig entlasten.

    Auch PHP 7 selbst cacht schon ein Menge.

    1. moin,

      Ja, warum willst Du nur die Ergebnisse der Bemühungen der Datenbank (die übrigens auch schon einen Cache hat) cachen und nicht gleich den kompletten Output? Den kann man sogar schon vorzippen und so den Server gehörig entlasten.

      Ich bastell mir meinen View aus Fragmenten zusammen. Wenn sich nur ein Fragment geändert hat aber alle anderen gleich blieben, so brauch sich nur ein View-Fragment um Daten aus DB bemühen. Der Rest der View-Fragmente holt sich eben das gecachte.

      lgmb

      1. Klassen die einmal kompiliert wurden, liegen als sog. Bytecode im Hauptspeicher. Ebenso können Templates, welche durch diese Klassen geladen werden, im Hauptspeicher verbleiben. Eine soche Technik ist möglich mit mod_perl und fast_cgi.

        Machs doch einfach, baue Dir eine Testumgebung, dann kannst Du dich mit solchen Techniken vertraut machen. Das bringt Dir mehr als hier im Forum immer wieder dieselben Fragen zu stellen!

        MfG

        1. Tach!

          Klassen die einmal kompiliert wurden, liegen als sog. Bytecode im Hauptspeicher. Ebenso können Templates, welche durch diese Klassen geladen werden, im Hauptspeicher verbleiben. Eine soche Technik ist möglich mit mod_perl und fast_cgi.

          PHP ist nicht Perl. Aber PHP hat seit Version 5.5 auch einen eingebauten OPCode-Cache (vorher nur optionale). Der arbeitet aber datei-basierend, also für Scripts und nicht (nur) für Klassen. Wenn Templates aus PHP-Code bestehen, dann natürlich auch für diese, denn das sind ja dann auch nur Script-Dateien. Wenn es sich um Dateien handelt, die etwas anderes als PHP-Code enthalten, der durch einen selbst geschriebenen Parser laufen muss, dann ist das jedenfalls nicht vom PHP-OPCode-Cache betroffen (nur der PHP-Code vom Parser selbst).

          Machs doch einfach,

          Machs uns doch einfach und antworte nicht immer mit Perl-Zeugs auf PHP-Fragen.

          dedlfix.

        2. moin,

          Klassen die einmal kompiliert wurden, liegen als sog. Bytecode im Hauptspeicher. Ebenso können Templates, welche durch diese Klassen geladen werden, im Hauptspeicher verbleiben. Eine soche Technik ist möglich mit mod_perl und fast_cgi.

          Aufgrund deines Wissens bin ich mir Sicher, dass das ne schöne Eigenschaft von Peal is. Aber…

          Machs doch einfach, baue Dir eine Testumgebung, dann kannst Du dich mit solchen Techniken vertraut machen. Das bringt Dir mehr als hier im Forum immer wieder dieselben Fragen zu stellen!

          …wie @dedlfix schon erwähnt hat sind die BuiltIn-Funktionen vermutlich Peal basierend und deswegen für PHP unbrauchbar 😕. Aber schön wäre es gewesen 😀.

          lgmb

          1. Das Equivalent zu mod_perl ist mod_php. Und fast_cgi kannst auch mit PHP machen.

            Und was builtinfunctionen betrifft: Das sind diejenigen Funktionen welche die Binary mitbringt. Also auch die PHP Binary bringt Builtinfunktionen mit und zwar jede Menge.

            Builtinfunktionen sind die Funktionen die auf php.net beschrieben sind. Builtin eben.

            MfG

            1. Das Equivalent zu mod_perl ist mod_php.

              Das ist nicht richtig. Anders als unter mod_perl hast Du unter mod_php getrennte Namensräume.

              1. Anders als unter mod_perl hast Du unter mod_php getrennte Namensräume.

                Also die Module die ich zu mod_perl kenne sind tatsächlich grottig in dieser Hinsicht. Was mich wirklich begeistert ist FastCGI. Nicht zuletzt deswegen weil mein FW damit läuft und sämtliche meiner Module fast_cgi_kompatibel sind respective der gesamten FW Klassenhierarchie 😉

                Aber da möchte bitte jeder für sich selbst herausfinden: Wie gesagt, einfach mal machen!

                1. Also die Module die ich zu mod_perl kenne sind tatsächlich grottig in dieser Hinsicht.

                  Die, die ich kenne, berücksichtigen den Umstand zumindest, oder nutzen ihn sogar.

                  Was mich wirklich begeistert ist FastCGI. Nicht zuletzt deswegen weil mein FW damit läuft und sämtliche meiner Module fast_cgi_kompatibel sind respective der gesamten FW Klassenhierarchie 😉

                  Das ist toll.

                  1. Genau! Sowas lernt man nicht hier im Forum. Das muss man sich schon selbst erarbeiten!

      2. Ich bastle mir meinen View aus Fragmenten zusammen.

        Freilich geht das auch mit Fragmenten (a.k.a. "Sniplets"). Dabei kann aber - JE NACH DEN UMSTÄNDEN - die Gültigkeitsprüfung "teuer" werden.

        1. moin,

          Ich bastle mir meinen View aus Fragmenten zusammen.

          Freilich geht das auch mit Fragmenten (a.k.a. "Sniplets"). Dabei kann aber - JE NACH DEN UMSTÄNDEN - die Gültigkeitsprüfung "teuer" werden.

          kann ich mir denken. Frisst das Performance?

          lgmb

          1. moin,

            Ich bastle mir meinen View aus Fragmenten zusammen.

            Freilich geht das auch mit Fragmenten (a.k.a. "Sniplets"). Dabei kann aber - JE NACH DEN UMSTÄNDEN - die Gültigkeitsprüfung "teuer" werden.

            kann ich mir denken. Frisst das Performance?

            Unter gewissen Umständen ... soll heißen, es bei einer extremen Anzahl an "Snipplets" und einer Vielzahl von Prüfungen, die vielleicht deutlich über filemtime auf einem localen Dateisystem hinausgehen ... Aber so klug bist Du selbst.

  3. Nochwas,

    Klassen und Klassenvariablen sind statische Gebilde, Instanzen hingegen nicht. Jetzt nehmen wir mal an, daß eine Klassenvariable bei jeder Instanzerstellung um 1 erhöht wird. Genau das zeigt ja das statische Verhalten: Jede neue Instanz findet diese Variable so vor wie sie von der letzten Instanz verlassen wurde.

    Ganz genauso wie die diese Zählvariable verhält es sich auch mit anderen Variablen die klassenweit deklariert wurden, also bspw. auch prepared Statements, Templates und auch die DB Verbindung selbst.

    So könnten in mod_php bereits beim Serverstart sämtliche Templates in den Hauptspeicher geladen werden was eine Klasse Templates tun könnte wenn sie beim Serverstart kompiliert wird. So könnte bei einem Request auf /foo.html die dazugehörige Templatedatei ohne Umschweife aus dem Hauptspeicher geladen werden was viel schneller geht als aus dem Dateisystem.

    Bei mod_php muss Du jedoch aufpassen daß persönliche Daten ($_SESSSION) nicht im Speicher hängenbleiben. Wie machen wir das? Richtig, solche Daten gehören nicht in Klassen organisiert sondern an die Instanz gebunden! Denn jede Instanz wird beim destroy aus dem Hauptspeicher entfernt. Einfaches Beispiel: Das Template für den Warenkorb kann jeder sehen, aber nicht das was drin ist.

    MfG

    1. Tach!

      Klassen und Klassenvariablen sind statische Gebilde, Instanzen hingegen nicht. Jetzt nehmen wir mal an, daß eine Klassenvariable bei jeder Instanzerstellung um 1 erhöht wird. Genau das zeigt ja das statische Verhalten: Jede neue Instanz findet diese Variable so vor wie sie von der letzten Instanz verlassen wurde.

      Ganz genauso wie die diese Zählvariable verhält es sich auch mit anderen Variablen die klassenweit deklariert wurden, also bspw. auch prepared Statements, Templates und auch die DB Verbindung selbst.

      Schön und gut, aber wenn das was mit Caching zu tun haben soll, muss der Speicher auch bestehenbleiben. Das ist bei PHP nicht der Fall.

      So könnten in mod_php bereits beim Serverstart sämtliche Templates in den Hauptspeicher geladen werden was eine Klasse Templates tun könnte wenn sie beim Serverstart kompiliert wird.

      Nein, das kann nicht, weil beim Serverstart keinerlei Scripte ausgeführt werden. Zudem gibt es in PHP keinen globalen Speicher, auf den von unterschiedlichen Requests aus zugegriffen werden könnte. Selbst wenn also beim Start ein Script ausgeführt werden würde, gibt es keine Möglichkeit, innerhalb einer Request-Bearbeitung auf dessen Daten zuzugreifen. Vielleicht ist das bei Perl oder mod_perl so, aber nicht in PHP oder mod_php oder PHP unter FCGI oder FPM.

      Es gibt lediglich zusätzliche Extensions, wie beispielsweise APC U(ser Cache), denen man über entsprechende Funktionsaufrufe Daten zum Speichern übergeben und wieder holen kann. Das ist ein Key-Value-Speicher und das Prozedere dazu ist auf gewisse Weise ähnlich wie Daten in ein DBMS zu speichern und von dort zu holen.

      Bei mod_php muss Du jedoch aufpassen daß persönliche Daten ($_SESSSION) nicht im Speicher hängenbleiben.

      Es bleiben bei PHP gar keine Daten im Speicher hängen, wenn ein Request beendet wird. Weder in $_SESSION noch in irgendwelchen anderen Variablen. Es gibt dieses Verhalten in anderen Systemen (z.B. ASP.NET), aber nicht in PHP.

      dedlfix.

      1. @dedlfix

        na wenn das so ist, da machen mod_php und FastCGI_php ja überhaupt gar keinen Sinn!

        Da kann man seine Zeit wahrlich besser vertreiben. Z.B. mit FastCGI in Perl. Da kann man sogar die Anzahl der Prozesse konfigurieren und sogar per Browser managen. Das macht FastCGI sogar für shared Hosting tauglich!

        MfG

        1. Tach!

          na wenn das so ist, da machen mod_php und FastCGI_php ja überhaupt gar keinen Sinn!

          Das würde ich so nun auch wieder nicht sagen, denn dass PHP an sich in diesen beiden Modi (zuzüglich FPM, denn das ist das was man heutzutage statt FCGI nehmen möchte) bereits vorgeladen ist, und damit die Startzeit deutlich geringer als bei herkömmlichem CGI ist, ist auch ein wesentlicher Vorteil. Zudem ist das Voraussetzung, damit APCU funktioniert. Einen externen Memcached anzusprechen geht zwar auch mit altem CGI, aber da konterkarriert ja die Startzeit von PHP den schnellern Zugriff gegenüber Dateisystem oder DBMS.

          Zudem existiert der Session-Mechanismus für das requestübergreifende Speichern von Daten (wenn auch per Default im Dateisystem) und ein OPCode-Cache. Template-Scripts sind also cache-fähig, solange sie PHP-Code sind.

          Da kann man seine Zeit wahrlich besser vertreiben. Z.B. mit FastCGI in Perl. Da kann man sogar die Anzahl der Prozesse konfigurieren und sogar per Browser managen. Das macht FastCGI sogar für shared Hosting tauglich!

          Ach, meinst du etwa, das wäre für die Kombination PHP und FCGI beziehungsweise FPM nicht möglich?

          dedlfix.

        2. Das macht FastCGI sogar für shared Hosting tauglich!

          Naja. Ich weiß ja nicht wieviel Arbeitsspeicher ein Server bräuchte, der Daten und Skripte von um die 3000 Kunden im Arbeitsspeicher bereit halten sollte. Perl::CGI::Fast nutzt FCGI und in der Apache-Dok zu mod_fcgi steht:

          However, the programs invoked by mod_fcgid continue to consume resources, so the administrator must weigh the impact of invoking a particular program once per request against the resources required to leave a sufficient number of instances running continuously.

          Mich wundert nicht, dass dann allerhand Einstellungen folgen, die eben den Sinn haben diese Prozesse zu begrenzen und zu beenden. Das war es dann - gerade im shared-Hosting für die Massen - mit "caching".

          Und nicht zuletzt: Wenn der steuernde Apache den Kind-Prozess (also einen "Worker") cancelt, dann dürfte auch

          So könnten in mod_php bereits beim Serverstart sämtliche Templates in den Hauptspeicher geladen werden was eine Klasse Templates tun könnte wenn sie beim Serverstart kompiliert wird.

          Bei Serverstart des Apache mit mod_php wird jedenfalls kein PHP-Skript kompiliert. Das gänge womöglich mit etwas wie:

          php -S localhost:8000 /var/www/local/uptime.php
          

          Allerdings wird im Shared Hosting aus gutem Grund (3000 Kunden könnten locker die maximale Zahl von 64536 Ports crashen) diese Möglichkeit ausgeschlossen. Z.B. in dem PHP so kompiliert wird, dass die Option '-S' nichts tut.

          1. Zu Deiner Aussage:

            Das macht FastCGI sogar für shared Hosting tauglich!

            ziehe ich mal vorsichtig das Fazit, dass in Abhängigkeit von der Trefferquote, die auf Grund der begrenzten Ressourcen zwingend um so geringer ausfällt je mehr Kunden/Skripte auf einem shared Server gehostet werden, der Einsatz von FastCGI sogar kontraproduktiv sein kann.

            1. Tach!

              Zu Deiner Aussage:

              Das macht FastCGI sogar für shared Hosting tauglich!

              ziehe ich mal vorsichtig das Fazit, dass in Abhängigkeit von der Trefferquote, die auf Grund der begrenzten Ressourcen zwingend um so geringer ausfällt je mehr Kunden/Skripte auf einem shared Server gehostet werden, der Einsatz von FastCGI sogar kontraproduktiv sein kann.

              Was wären denn die Alternativen?

              CGI fällt aus wegen Langsamkeit.

              PHP als Modul fällt aus wegen Sicherheit. Da dort alles unter derselben Kennung läuft, kann man Kunden nicht voneinander trennen. Den SafeMode, der dieses Problem zu lösen vorgegeben hatte, es aber nicht wirklich konnte, gibt es nicht mehr.

              Bleibt nur noch FCGI und FPM.

              dedlfix.

              1. ziehe ich mal vorsichtig das Fazit, dass in Abhängigkeit von der Trefferquote, die auf Grund der begrenzten Ressourcen zwingend um so geringer ausfällt je mehr Kunden/Skripte auf einem shared Server gehostet werden, der Einsatz von FastCGI sogar kontraproduktiv sein kann.

                Was wären denn die Alternativen?

                Nun, große Webauftritte - also diejenigen, wo die Frage relevant wird, gehören aus einer ganzen Anzahl guter Gründe (Datensicherheit, Leistung, ...) nicht auf Hosts, auf denen tausende verschiedene Kunden ihre Webseiten der Öffentlichkeit feilbieten.

                Google hostet ja auch nicht auf einem Rasperry PI...

                Und ab dem eigenen (virtuellen) Server entfallen die Gründe, die mod_php verbieten, gleichzeitig hat man es regelmäßig auch nicht mehr mit einer großen Anzahl selten genutzter Skripte, sondern mit einer geringeren Anzahl häufig genutzter Skripte zu tun. Und schon funktioniert auch das Cachen wieder.

                1. Tach!

                  ziehe ich mal vorsichtig das Fazit, dass in Abhängigkeit von der Trefferquote, die auf Grund der begrenzten Ressourcen zwingend um so geringer ausfällt je mehr Kunden/Skripte auf einem shared Server gehostet werden, der Einsatz von FastCGI sogar kontraproduktiv sein kann.

                  Was wären denn die Alternativen?

                  Nun, große Webauftritte - also diejenigen, wo die Frage relevant wird, gehören aus einer ganzen Anzahl guter Gründe (Datensicherheit, Leistung, ...) nicht auf Hosts, auf denen tausende verschiedene Kunden ihre Webseiten der Öffentlichkeit feilbieten.

                  Soweit so klar, aber es kann ja nicht die Lösung von Massenhostern sein, jede Kundenwebsite so aufzublasen, dass sie einen eigenen Server brauchen. 😉

                  Also wenn wir mal beim Thema bleiben, was der Hoster im Falle vieler kleiner Kunden machen sollte, was wäre denn da anstrebenswert?

                  dedlfix.

                  1. Soweit so klar, aber es kann ja nicht die Lösung von Massenhostern sein, jede Kundenwebsite so aufzublasen, dass sie einen eigenen Server brauchen.

                    Das machen stets die Kunden selbst (Typo3, exzessiver Einsatz von Frameworks, serverseitiges Einbinden von Kram mit API-Zugriffen...). Die Massenhoster sind nicht daran interessiert, dass irgendwelche Kunden viel Last verursachen oder dass deren Skripte auch nur lange laufen.

                    Also wenn wir mal beim Thema bleiben, was der Hoster im Falle vieler kleiner Kunden machen sollte, was wäre denn da anstrebenswert?

                    Er hat vor allem dafür zu sorgen, dass ein einzelner Kunde den Webserver nicht als für € 4,99 pro Monat gemieteten Großrechner missbraucht - damit ihm nicht die 3999 anderen kündigen.

                    Im Handbuch steht dazu so Einiges. Hinzu kommen noch (Disk-)quota e.t.c.

                    Auch sollte ein solcher Hoster mit apachetop, htop, ps und Co. immer mal nachsehen, was so geht. Das kann einfach oder kompliziert gemacht werden.

                    1. Auch sollte ein solcher Hoster mit apachetop, htop, ps und Co. immer mal nachsehen, was so geht. Das kann einfach oder kompliziert gemacht werden.

                      Beispiel für "kompliziert" (Sowas geht nicht nur mit der Netzlast...)

          2. Das macht FastCGI sogar für shared Hosting tauglich!

            Das heißt, daß man beim Neustart des FastCGI Servers nicht den Apache neu starten muss: Der FastCGI Server ist mandantenfähig, die Maintenance kann über den VirtualHost erfolgen.

            Wenn der FastCGI Server gestoppt wurde, kommt der beim ersten Request auf den VirtualHost automatisch wieder hoch, ganz unabhängig vom Apache Webserver. In Letzterem muss dazu nur das Modul geladen sein (LoadModule fastcgi_module modules/mod_fastcgi.so in Global Config Apache 2).

            Genau das macht FastCGI shared hosting tauglich. Und wie bereits festgestellt, die Anzahl der Prozesse ist konfigurierbar, damit lässt sich auch der Speicherbedarf abschätzen bzw. darauf abstimmen.

            Ansonsten läuft ein FastCGI sehr CPU gefällig. Ich hatte Webserver die sind jeden morgen in die Knie gegangen weil bei jedem Request ein native CGI Prozess gestartet wurde, beim Start entsteht der meiste Overhead. Mit der Umstellung auf FastCGI war dieses Problem erledigt.

            Woran man immer wieder seine Freude hat ist die Performance in FastCGI. Und vor Allem auch die hier beschriebene OO-Programmiertechnik die man gerade mit FastCGI sehr profitable nutzen kann.

            MfG

    2. Nochwas als Ergänzung,

      Klassen und Klassenvariablen sind statische Gebilde,

      deswegen werden Klassenmethoden auch Statische Methoden genannt, eben weil sie sich statisch verhalten.

      MfG

    3. moin,

      Klassen und Klassenvariablen sind statische Gebilde, [...]

      …und…

      Ganz genauso wie die diese Zählvariable [...]

      Entschuldigung, aber was hat das mit der Eingangsfrage die ich stellte zutun?

      So könnten in mod_php bereits beim Serverstart sämtliche Templates in den Hauptspeicher geladen werden was eine Klasse Templates tun könnte wenn sie beim Serverstart kompiliert wird. [...]

      Deine Lösung sind schön und gut, aber ich arbeite nicht mit Peal zum wiederholten Male.

      Ich bin Dir sehr Dankbar wenn du deine Erfahrungen, Vorgehensweisen und Lösungsansätzen zu Fragen die ich hier im Forum stelle preis gibst. Das ist auch Zweck dieses Forums 😉. Aber es nicht förderlich, teils sogar hinderlich, wenn du Peal-spezifisch argumentierst. Das stiftet grade bei mir Verwirrung 😕.

      lgmb

      1. Sorry,

        Du verstehst nicht. Ich beschreibe hier OOP Dinge die allgemein gültig sind. Also nichts Perl-spezifisches.

        MfG

        1. moin,

          Du verstehst nicht. Ich beschreibe hier OOP Dinge die allgemein gültig sind. Also nichts Perl-spezifisches.

          Das weis ich und es ist auch super verständlich und es ist allgemein, das anerkenne ich ja auch eben bei dir 😉. Das war eine allgemeine Bitte an dich und generell an alle die ich hier ausgesprochen habe, nix weiter 😉. Sorry wenn das nicht so rüber gekommen ist.

          lgmb