3,32:
In Zeiten des superschnellen Internets sind die Webentwickler mehr denn je gefordert ihre Webapplikationen möglichst performant zu erstellen. Zu Zeiten des 56k-Modems hat es noch niemanden wirklich interessiert, wie lange der Server braucht, um die Daten aufzubereiten, da es im Vergleich zur Datenübertragung eine verschwindend geringe Zeit war. Im Hier und Jetzt sieht das jedoch völlig anders aus: Die Serververarbeitungszeit kann schon mal die größte Zeitspanne im gesamten Ladevorgang darstellen.
Eine wichtige und effektive Methode, um diese Zeit zu verringern, ist dabei das Cachen. Caching bedeutet nicht nur Geschwindigkeitszuwachs, sondern auch weniger Serverauslastung. Ein wünschenswertes Ergebnis also und die Methode ist keineswegs neu. Im Gegenteil: so ziemlich alle Internetsurfer benutzen einen Cache: den Browsercache. Wahrscheinlich wissen 95% der User nicht das sie ihn benutzen, aber er ist dennoch ein Feature was unglaubliche Ladezeit einspart. Der Browsercache ist aber nicht die einzige Art die den Webentwicklern zur Verfügung steht, er soll hier dennoch erläutert werden, zusammen mit seinen Verwandten.
Cache Allgemein
Ein Cache ist ein Speicher um Daten, die bereits einmal vorlagen, beim der nächsten Anfrage schneller zur Verfügung stellen zu können. Schneller zur Verfügung gestellt werden können diese Daten, indem der Cache ein schnelleres Speichermedium benutzt als die Originaldaten oder aber indem aufwendig generierte Daten überhaupt erst mal gespeichert werden, die sonst jedes Mal neu generiert werden müssten. Es gibt Caches sowohl im Hard- als auch im Softwarebereich.
Browsercache
Der Browsercache legt statische Dateien wie Bilder, CSS- und JS-Files auf dem Client-Rechner ab. Das hat zur Folge, dass bei einer erneuten Anfrage des Browsers diese Dateien nicht erneut aufwendig über das Netzwerk transferiert werden müssen, sondern schnell von der Festplatte des Benutzers geholt werden können. Generell können alle Dateien gecached werden, es macht jedoch bei dynamischen Dateien häufig keinen Sinn. Ob Dateien aus dem Cache geholt werden oder nicht, entscheidet der Browser anhand der vom Webserver gelieferten Header. Hier werden zum Beispiel das Änderungsdatum und die Größe der Datei übermittelt und dadurch weiß der Browser, ob sich die Datei auf dem Server verändert hat oder ob diese den gleichen Inhalt wie die auf der Festplatte hat. Über diese Header des HTTP-Requests lässt sich somit auch das Cache-Verhalten des Browsers über PHP und/oder den Webserver steuern.
Datenbankcache
Die meisten Datenbanksysteme haben auch einen eigenen internen Cache. Dort werden Ergebnisse von Abfragen zwischengespeichert um bei einer erneuten Anfrage die Daten schneller bereit stellen zu können. Das klappt deswegen, weil die Ergebnisse im Arbeitsspeicher des Servers gehalten werden und der Arbeitsspeicher ist ein wesentlich schnelleres Medium als die Festplatte. Außerdem werden die Daten bereits aufbereitet gelagert, somit entfallen einige interne Schritte der Datenbank, die sonst Zeit kosten. Einige Datenbankabfragen können wegen der unglücklichen Formulierung nicht gecached werden, deshalb sollte man sowas im Hinterkopf behalten:
Nicht-cachebar:
Cachebar:
Die beiden Queries liefern dasselbe Ergebnis, daher sollte man hier also bspw. mit PHP das aktuelle Datum in das Query einfügen, da die Datenbank nicht davon ausgehen kann das interne Funktionen immer das gleiche Ergebnis liefern. Der Cache der Datenbank ist weitestgehend unsichtbar, lässt sich aber dennoch über Servereinstellungen konfigurieren und über bestimmte Queries auch etwas steuern.
PHP Cache-Erweiterungen
PHP Erweiterungen wie APC (Alternative PHP Cache) organisieren das cachen des PHP-Codes selber. Ist der Code einmal interpretiert worden, so muss sich der PHP Interpreter nicht erneut darum kümmern, sondern es kann direkt aus dem Shared-Memory des Webservers aufgerufen werden. Es gibt unterschiedliche Cache-Erweiterungen die unterschiedlich arbeiten, die meisten bieten jedoch den Entwicklern die Möglichkeit Daten dort abzulegen und beim nächsten Zugriff diese Daten direkt aus dem Arbeitsspeicher statt aus einer langsameren externen Quelle zu holen.
Eigenen Cache nutzen
Bei Webapplikationen wie CMS Systemen kann es durchaus Geschwindigkeit bringen wenn man zum Beispiel den Inhalt des Frontends in Dateien zwischenspeichert, um zu vermeiden das alle Websitebetrachtungen die Datenbank belasten. Eine Website die sich nur alle paar Monate mal ändert, kann somit fast ausschließlich ohne Datenbankzugriffe auskommen. Auch dies ist Caching und dabei gibt es einige Punkte die beachtet werden müssen. Der Hauptpunkt dabei ist die Gültigkeit des gecachten Inhalts. Woher weiss ich wann so eine Datei für mein Frontend nicht mehr den aktuellen Inhalt hat? Ich habe ja kein „Änderungsdatum“ des Datensatzes in der Datenbank, wie beim Browsercache und selbst wenn ich eines mit speichern würde, so müsste ich den Datensatz dann trotzdem aus der Datenbank holen und habe somit nichts gewonnen. So manch einer mag nun auf die Idee kommen das die erstellten Dateien einfach in einem bestimmten Rhythmus via Cronjob oder ähnlichem neu erstellt werden. Das funktioniert in manchen Anwendungen auch, hat aber auch einige Nachteile. Bei oben genannter Website (die sich kaum ändert) würde das sehr gut funktionieren, bedeutet aber gleichzeitig auch wieder mehr Abfragen als nötig und wichtige Änderungen werden auf der Website erst nach den nächsten Cache-lösch-Zyklus sichtbar. Eine erweiterte Variante davon wäre, die Dateien mit einer Lebensdauer zu versehen. Dann hätte man für unterschiedliche Dateien unterschiedliche Möglichkeiten und man kann beim Aufruf der Website prüfen ob der Cache noch gültig ist und ggf. die Daten direkt in der Anfrage des Users neu generieren. Dann würden die Daten nur aus der Datenbank abgefragt werden, wenn die Gültigkeit abgelaufen ist und die langsamere Variante bekommt nur der allererste Aufruf zu spüren. Die beste Möglichkeit um zu testen ob der Cache noch gültig ist, ist es gar nicht zu testen. Das heisst also man hält die erstellten Dateien permanent auf dem neusten Stand. Da kommt sicher die Frage auf „wie soll das denn gehen?“. Nun, ein minütlicher Cronjob der die Dateien neu generiert ist natürlich Blödsinnig und würde den Server wahrscheinlich mehr belasten also ohne Cache zu arbeiten. Also müssen wir am anderen Ende ansetzten, am Backend, dort wo die Daten geändert werden. Wir müssen also bei jeder Datenänderung die entsprechende betroffenen Cache-Dateien entweder direkt aktualisieren oder aber deren Gültigkeit auf 0 setzen. Da stellt sich die Frage „soll ich jetzt den Datenaustausch zwischen Applikation und Datenbank belauschen und bei jeden INSERT oder UPDATE“ die Cache-Aktualisierung durchführen?“. Die Antwort darauf lautet „Jein“. Ja im Bezug auf „bei jedem INSERT und UPDATE die Cache-Aktualisierung durchführen“ und nein im Bezug auf das lauschen. Ganz wichtig hierbei ist nämlich die Applikations-Struktur. Habe ich meine Applikation in einem ordentlichen objektorientiertem Design erstellt, zum Beispiel mit einem guten Framework und einem OR-Mapper, dann fällt es leicht eine Zwischenschicht zwischen Applikation und Datenbank zu setzen, die den Cache verwaltet und anhand der Datenbankänderungen entsprechend aktualisiert. Bei prozeduraler Programmierung kann das ganze leider je nach Struktur und Größe des Programms um einiges Aufwendiger werden.
Haben wir dieses dann umgesetzt, ist das ganze schon fast perfekt, aber nur fast. Leider kann man sich nicht immer darauf verlassen, dass die eigene Anwendung die einzige Möglichkeit ist, die Daten zu verändern. Unser Cache bekommt aber nur Änderungen mit, die auch mit unserer Applikation gemacht wurden. Man sollte also als Hintertürchen die verschiedenen Möglichkeiten kombinieren, um ein für sich funktionierendes Gesamtkonzept zu bekommen.
Happy Caching!
Eine wichtige und effektive Methode, um diese Zeit zu verringern, ist dabei das Cachen. Caching bedeutet nicht nur Geschwindigkeitszuwachs, sondern auch weniger Serverauslastung. Ein wünschenswertes Ergebnis also und die Methode ist keineswegs neu. Im Gegenteil: so ziemlich alle Internetsurfer benutzen einen Cache: den Browsercache. Wahrscheinlich wissen 95% der User nicht das sie ihn benutzen, aber er ist dennoch ein Feature was unglaubliche Ladezeit einspart. Der Browsercache ist aber nicht die einzige Art die den Webentwicklern zur Verfügung steht, er soll hier dennoch erläutert werden, zusammen mit seinen Verwandten.
Cache Allgemein
Ein Cache ist ein Speicher um Daten, die bereits einmal vorlagen, beim der nächsten Anfrage schneller zur Verfügung stellen zu können. Schneller zur Verfügung gestellt werden können diese Daten, indem der Cache ein schnelleres Speichermedium benutzt als die Originaldaten oder aber indem aufwendig generierte Daten überhaupt erst mal gespeichert werden, die sonst jedes Mal neu generiert werden müssten. Es gibt Caches sowohl im Hard- als auch im Softwarebereich.
Browsercache
Der Browsercache legt statische Dateien wie Bilder, CSS- und JS-Files auf dem Client-Rechner ab. Das hat zur Folge, dass bei einer erneuten Anfrage des Browsers diese Dateien nicht erneut aufwendig über das Netzwerk transferiert werden müssen, sondern schnell von der Festplatte des Benutzers geholt werden können. Generell können alle Dateien gecached werden, es macht jedoch bei dynamischen Dateien häufig keinen Sinn. Ob Dateien aus dem Cache geholt werden oder nicht, entscheidet der Browser anhand der vom Webserver gelieferten Header. Hier werden zum Beispiel das Änderungsdatum und die Größe der Datei übermittelt und dadurch weiß der Browser, ob sich die Datei auf dem Server verändert hat oder ob diese den gleichen Inhalt wie die auf der Festplatte hat. Über diese Header des HTTP-Requests lässt sich somit auch das Cache-Verhalten des Browsers über PHP und/oder den Webserver steuern.
Datenbankcache
Die meisten Datenbanksysteme haben auch einen eigenen internen Cache. Dort werden Ergebnisse von Abfragen zwischengespeichert um bei einer erneuten Anfrage die Daten schneller bereit stellen zu können. Das klappt deswegen, weil die Ergebnisse im Arbeitsspeicher des Servers gehalten werden und der Arbeitsspeicher ist ein wesentlich schnelleres Medium als die Festplatte. Außerdem werden die Daten bereits aufbereitet gelagert, somit entfallen einige interne Schritte der Datenbank, die sonst Zeit kosten. Einige Datenbankabfragen können wegen der unglücklichen Formulierung nicht gecached werden, deshalb sollte man sowas im Hinterkopf behalten:
Nicht-cachebar:
Code:
SELECT * FROM tabelle WHERE datum = DATE_FORMAT(NOW(),’%y-%d-%m’)
Code:
SELECT * FROM tabelle WHERE datum = ‘2010-12-10’
PHP Cache-Erweiterungen
PHP Erweiterungen wie APC (Alternative PHP Cache) organisieren das cachen des PHP-Codes selber. Ist der Code einmal interpretiert worden, so muss sich der PHP Interpreter nicht erneut darum kümmern, sondern es kann direkt aus dem Shared-Memory des Webservers aufgerufen werden. Es gibt unterschiedliche Cache-Erweiterungen die unterschiedlich arbeiten, die meisten bieten jedoch den Entwicklern die Möglichkeit Daten dort abzulegen und beim nächsten Zugriff diese Daten direkt aus dem Arbeitsspeicher statt aus einer langsameren externen Quelle zu holen.
Eigenen Cache nutzen
Bei Webapplikationen wie CMS Systemen kann es durchaus Geschwindigkeit bringen wenn man zum Beispiel den Inhalt des Frontends in Dateien zwischenspeichert, um zu vermeiden das alle Websitebetrachtungen die Datenbank belasten. Eine Website die sich nur alle paar Monate mal ändert, kann somit fast ausschließlich ohne Datenbankzugriffe auskommen. Auch dies ist Caching und dabei gibt es einige Punkte die beachtet werden müssen. Der Hauptpunkt dabei ist die Gültigkeit des gecachten Inhalts. Woher weiss ich wann so eine Datei für mein Frontend nicht mehr den aktuellen Inhalt hat? Ich habe ja kein „Änderungsdatum“ des Datensatzes in der Datenbank, wie beim Browsercache und selbst wenn ich eines mit speichern würde, so müsste ich den Datensatz dann trotzdem aus der Datenbank holen und habe somit nichts gewonnen. So manch einer mag nun auf die Idee kommen das die erstellten Dateien einfach in einem bestimmten Rhythmus via Cronjob oder ähnlichem neu erstellt werden. Das funktioniert in manchen Anwendungen auch, hat aber auch einige Nachteile. Bei oben genannter Website (die sich kaum ändert) würde das sehr gut funktionieren, bedeutet aber gleichzeitig auch wieder mehr Abfragen als nötig und wichtige Änderungen werden auf der Website erst nach den nächsten Cache-lösch-Zyklus sichtbar. Eine erweiterte Variante davon wäre, die Dateien mit einer Lebensdauer zu versehen. Dann hätte man für unterschiedliche Dateien unterschiedliche Möglichkeiten und man kann beim Aufruf der Website prüfen ob der Cache noch gültig ist und ggf. die Daten direkt in der Anfrage des Users neu generieren. Dann würden die Daten nur aus der Datenbank abgefragt werden, wenn die Gültigkeit abgelaufen ist und die langsamere Variante bekommt nur der allererste Aufruf zu spüren. Die beste Möglichkeit um zu testen ob der Cache noch gültig ist, ist es gar nicht zu testen. Das heisst also man hält die erstellten Dateien permanent auf dem neusten Stand. Da kommt sicher die Frage auf „wie soll das denn gehen?“. Nun, ein minütlicher Cronjob der die Dateien neu generiert ist natürlich Blödsinnig und würde den Server wahrscheinlich mehr belasten also ohne Cache zu arbeiten. Also müssen wir am anderen Ende ansetzten, am Backend, dort wo die Daten geändert werden. Wir müssen also bei jeder Datenänderung die entsprechende betroffenen Cache-Dateien entweder direkt aktualisieren oder aber deren Gültigkeit auf 0 setzen. Da stellt sich die Frage „soll ich jetzt den Datenaustausch zwischen Applikation und Datenbank belauschen und bei jeden INSERT oder UPDATE“ die Cache-Aktualisierung durchführen?“. Die Antwort darauf lautet „Jein“. Ja im Bezug auf „bei jedem INSERT und UPDATE die Cache-Aktualisierung durchführen“ und nein im Bezug auf das lauschen. Ganz wichtig hierbei ist nämlich die Applikations-Struktur. Habe ich meine Applikation in einem ordentlichen objektorientiertem Design erstellt, zum Beispiel mit einem guten Framework und einem OR-Mapper, dann fällt es leicht eine Zwischenschicht zwischen Applikation und Datenbank zu setzen, die den Cache verwaltet und anhand der Datenbankänderungen entsprechend aktualisiert. Bei prozeduraler Programmierung kann das ganze leider je nach Struktur und Größe des Programms um einiges Aufwendiger werden.
Haben wir dieses dann umgesetzt, ist das ganze schon fast perfekt, aber nur fast. Leider kann man sich nicht immer darauf verlassen, dass die eigene Anwendung die einzige Möglichkeit ist, die Daten zu verändern. Unser Cache bekommt aber nur Änderungen mit, die auch mit unserer Applikation gemacht wurden. Man sollte also als Hintertürchen die verschiedenen Möglichkeiten kombinieren, um ein für sich funktionierendes Gesamtkonzept zu bekommen.
Happy Caching!
Kommentar