Seitenaufbau mit PHP Caching beschleunigen
Meine Startseite ist in letzter Zeit ziemlich lahm geworden; selbst mit einer DSL-Verbindung war sie unter Umständen erst nach 5-10 Sekunden komplett geladen. Das liegt natürlich daran, dass dynamische Seiten bei jedem Aufruf erst mal zusammengebaut werden müssen, was eigentlich unnötig ist. Also habe ich mir diverse PHP Cache-Lösungen angesehen, die aber alle viel zu umfangreich und überladen waren. Als ich es schon aufgeben und selbst etwas schreiben wollte, fand ich die PHP Klasse ez_cache, die genau das macht, was ich will: Wird eine Seite aufgerufen, prüft ez_cache, ob diese Seite im Cache-Verzeichnis liegt, wenn ja, wird die Seite aus dem Cache angezeigt, wenn nicht, wird sie normal erzeugt und anschließend im Cache-Verzeichnis abgelegt. Nach einer frei wählbaren Zeit (in meinem Fall 60 Minuten) wird die Cache-Datei mit einer aktuellen Version überschrieben.
Eingebunden wird ez_cache mit wenigen Zeilen:
include 'ez_cache.class.php';
$ez = new ez_cache;
$ez->setup();
if(!$ez->use_cache()) {
hier steht alles das (PHP, HTML), was
in den Cache geschrieben werden soll
}
$ez->end();
Einfacher geht’s nicht. Damit man allerdings nicht irgendwann die komplette Website im Cache-Verzeichnis liegen hat, sollte man Cache-Dateien, die älter als die Verfallszeit sind, regelmäßig löschen. Ich habe dazu die Funktion cacheclean() geschrieben, die bei jedem Seitenaufruf automatisch ausgeführt wird:
function cacheclean($all = "") {
$cachefolder = "/Server/Pfad/zum/Cache-Verzeichnis/";
$handle = opendir($cachefolder);
while ($cachefile = readdir($handle)) {
if ($all == "all") {
@unlink($cachefolder.$cachefile);
} else {
$cachedate = filectime($cachefolder.$cachefile);
if ($cachedate < (time() - (60*60))) {
@unlink($cachefolder.$cachefile);
}
}
}
}
Wenn man der Funktion das Argument "all" übergibt, wird der gesamte Inhalt des Cache-Verzeichnisses gelöscht. Warum? Weil ein neuer Kommentar im ungünstigsten Fall erst nach einer Stunde angezeigt wird, wenn nämlich die entsprechende Cache-Datei erst dann aktualisiert wird. Sendet jemand also einen Kommentar oder einen TrackBack, wird gleichzeitig das Cache-Verzeichnis mit cacheclean("all") geleert, damit der Kommentar auch sofort und auf allen Seiten angezeigt wird. Das gleiche gilt natürlich, wenn ich einen neuen Eintrag veröffentliche, auch da müssen alle Cache-Dateien gelöscht werden.
Es hat sich gelohnt: Die Serverlast hat deutlich abgenommen, ganz zu schweigen vom Seitenaufbau z. B. der Startseite, der jetzt im Vergleich zu vorher ca. 5-10 mal schneller vonstatten geht.
Ähnliche Beiträge:
I’ve Been Careless – Sicherheitsprobleme bei Technorati Happy Birthday
Kommentare:
Bei den Kommentaren handelt es sich um fremde Inhalte, die sich „esse est percipi“ nicht zueigen macht. Verantwortlich für den Inhalt eines Kommentars ist der jeweilige Verfasser.
Kann man das auch in Textpattern einbinden? Gilt das für alle PHP-Lösungen?
Das gilt generell für alle PHP-Lösungen. Man sollte aber darauf achten, was man alles ‘cached’. Um diesen Kommentar zu verfassen, musste ich erst alle Eingaben (Name, e-Mail-Adresse, Website) von Nick aus den Textfeldern löschen…
Uh, ein Nachteil. Bei mir tauchte das nicht auf.
Ein großer Nachteil, der aber schon abgestellt ist. Eigentlich hätte das gar nicht passieren dürfen, da mit dem Klick auf „Abschicken“ gleichzeitig der komplette Cache gelöscht wird. Ich habe jetzt die Kommentarseiten aber komplett vom Caching ausgenommen, da dürfte dann so ein faux pas nicht mehr passieren …
Das heisst also, in jede PHP-Datei von Textpattern müsste man dies einbauen? Zur Sicherheit?
WIrd damit auch dein RSS-Feed schneller? Der braucht beim Laden in Sage (Firefox-Extension) nämlich mit Abstand am längsten!
Prinzipiell ist das eine gute Sache. Für mich hat sich subjektiv jetzt nichts an der Ladezeit geändert, denn die war auch vorher ganz gut. Das mag aber auch an meinem Cache liegen.
Diese Methode gefällt mir zwar auch, aber nicht so gut wie Turck MMCache. Denn bei dynamisch Seiten, die auch weiterhin ohne Abstriche dynamisch bleiben sollen, ist das Kompilieren der Skripte (teilweise mit Caching verbunden) noch eine Ecke besser. http://turck-mmcache.sourceforge.net/index_old.html#about
Kompilate (von Skriptsprachen) sind nicht zwangsläufig schneller als deren interpretierte Pendants; nur Michael kennt seinen Code und weiß, wo die Bottlenecks sind. Spricht aber auch nix dagegen, das Caching einem Spezialisten zu überlassen und einen Squid (oder einen anderen Proxy) vorzusetzen. Ich habe das Performance-Problem mal für einen bestehenden PHP-Shop evaluiert und bin danach bei Tomcat und Servlets gelandet…
[werbung an]
Gerade die Möglichkeit, ein Connection-Pooling (OK, Michael verwendet – glaube ich – keine Datenbank) zu implementieren und oft benötigte Entitäten im Applikations-Scope „leben“ zu lassen, machen die Java-Lösung zu einer eleganten Alternative. [werbung aus]
@Martin
*bahnhof* :-)
Mir ist nur aufgefallen, dass die Startseite super schnell ist. Wenn man eine Artikelseite aufruft, zeigt sich der Text zuerst kurz ohne die CSS-Formatierungen. Erst eine halbe Sekunde später springt dann das CSS rettend ein. Kann das etwas mit dem Caching zu tun haben? Früher ist mir das hier nicht aufgefallen.
System/Browser/Leitung: OS X 10.4.1 mit Safari 2.0 an 1,5MBit (Mac mini 1,4GHz, 1GB RAM)
Mit Firefox passiert das nicht. Vielleicht wird dort die verfrühte Anzeige unterdrückt. Es dauert nämlich etwas länger.
@Grady: Squid ist ein Proxy, den man vor seinen Apache setzen kann und der das Caching quasi unabhängig vom dynamisierten Content implementiert. Der User richtet damit seine Anfragen an Squid und der entscheidet, ob statischer (und somit bereits erechneter) Content aus dem Cache ausgeliefert wird, oder ob der Inhalt ‘outdated’ ist. In letzterem Fall verlangt er vom PHP-Prozess ein erneutes Berechnen und übernimmt das Ergebnis in seinen Cache, um nachfolgende Anfragen (eine definierte Zeit lang) wieder aus dem Cache zu füttern…
Die kritische Bemerkung gegen Compiler richtete sich gegen den unkritischen Ansatz „Meine PHP-Anwendung ist zu langsam, kompiliere ich sie halt.“ Uninspirierte Programmierung kann auch ein langsames Kompilat zur Folge haben… :-)
@Martin
Ok, danke. Mir ging es mehr um solche Begriffe wie „Connection-Pooling“ und „Applikations-Scope“... Da hilft für mich wohl nur Nachsitzen, um das alles zu verstehen. ;-)
OK, mal ganz simpel erklärt. ConnectionPooling widmet sich (unter Java) dem Problem, dass der Aufbau einer Verbindung zur Datenbank immer ein wenig Zeit kostet. Beim Start der (Web-)Applikation werden einfach n Verbindungen (Handles) aufgebaut, die dann während der ganzen Laufzeit offen bleiben. Diese offenen Verbindungen werden in einer Pool-Klasse verwaltet. Statt dann nach dem Schema „Datenbankverbindung aufbauen -> Query abfeuern -> Resultset holen -> Datenbankverbindung schliessen“ zu verfahren, macht man „Verbindung aus dem Pool holen -> Query abfeuern -> Resultset holen -> Datenbankverbindung in den Pool zurücklegen“. Dabei steckt der Hirnschmalz in der Pool-Klasse, die genau Buch über den Zustand jedes einzelnen Handles führt. Diese Klasse stellt sicher, dass nur ‘idle’ Connections zur Verfügung gestellt werden… Wenn Du darüber mehr lesen willst, google mal nach Jakarta DBCP. Die einzige Möglichkeit unter PHP effizienter mit Datenbankverbindungen umzugehen, wäre ein ‘pconnect’ – echtes Pooling geht da aber viel weiter.
Der Applikationsscope ist wieder so ein Alleinstellungsmerkmal von java-basierten Web-Anwendungen. Er repräsentiert einen applikationsweiten Speicherbereich. Sicherlich kennst Du globale Variablen unter PHP. Stell Dir nun eine Art „Über“-globale Variable vor, die nicht nur innerhalb eines Skripts (während eines Request) zu Verfügung steht, sondern über alle Request und Skripte hinaus! Damit kann man sehr schön Redundanz bei Datenbank-Zugriffen (oder jeglichen rechenintensiven Algorithmen) sparen; man fragt die DB nur einmal (beim Start der Webanwendung) und teilt das ermittelte Ergebnis mit allen Prozessen, die später danach fragen… Der „größte“ Scope unter PHP wäre übrigens die Session.
Ich hoffe, das war einigermaßen verständlich.
Lieber Herr Preidel, ihre Seite ist im Prinzip schneller geworden, aber es dauert, bevor ich ihre Seite starte, immer 2-3 Sekunden, bis es dann gestartet werden kann. An Safari bei mir kann es nicht liegen, denn der Verlauf wird immer wieder gelöscht. Irgendwas mit PHP lässt Safari und Firefox am Anfang langsam werden, dann geht´s schnell.
Kommentar schreiben:
FAQ (Häufig gestellte Fragen)
Kommentare:
- SmartFehler-Redaktion zu Xiaomi Mi Smart Fan Ventilator in Home Assistant einbinden
- Michael Preidel zu BBEdit-Tipp: Einrücken mit Tab-Taste
- Dirk zu BBEdit-Tipp: Einrücken mit Tab-Taste
- Michael Preidel zu Pop-up Fenster sind zurück – ein bisschen
- Bock zu Pop-up Fenster sind zurück – ein bisschen
- Michael Preidel zu Pasta dell’Orto
Schlagwörter