Tag Archive for 'Performance'

JavaScript Performance: Warum ‘nativ’ nicht immer besser ist.

Eigentlich wollte ich den heutigen Artikel neuen JavaScript Array-Features widmen, die am kommen oder schon da sind (forEach(), indexOf(), Iteratoren, Generatoren, etc.). Garnieren wollte ich das ganze mit ein paar Benchmarks, um bestenfalls zu zeigen dass die ‘nativen’ Arraymethoden der Browser meine selbstgeschriebenen Equivalente vor Neid erblassen lassen und was die Zukunft bringt. Doch das wäre wohl zu einfach gewesen…

Das Ergebnis war überraschend: Während meine Benchmarks im v8 (d.h. die JS-Engine von Chrome) zwar zeigten, dass manche meiner Methoden nur einen kleinen Tick langsamer waren (manche aber auch schneller), war es bei Spidermonkey (die Firefox engine) genau umgekehrt: Sobald dort die Tracing Engine aktiviert war (was Standard seit FF > 3.5 ist), lief mein eigener Code mit einer viel besseren Performance (z.T um den Faktor x6) als die ‘nativen’ SpiderMonkey-Methoden, die in C++ geschrieben waren.

Bildschirmfoto 2012 01 12 um 10.31.10 300x170 JavaScript Performance: Warum nativ nicht immer besser ist.

Was komisch klingt liegt an der Art und Weise wie Fuchs optimiert: Mein eigener Code wird zur Laufzeit ge’traced’ (grob gesagt: Es wird verfolgt, ob die Typen der Variablen gleichbleibend sind und dementsprechend wenn möglich auf Typkonvertierungen und -überprüfungen verzichtet – wer Details will findet eine gute Einführung im Mozilla Blog ). Dementsprechend werden bei meinem selbstgeschriebenen Code weniger Operationen pro Durchgang benötigt. Bei den nativen Methoden ist dass anscheinend anders: Eine kleine Wanderung in den C++ Code von Spidermonkey zeigte, dass z.B. die Array.prototype.every() Methode Typen immer überprüft und konvertiert und ich schätze, dass hier derzeit kein Tracing stattfindet.

Die größten Performancesprünge lagen dabei interessanterweise bei Methoden, die Funktionen als Argumente nehmen, wie z.b. Array.map(), Array.filter(), Array.forEach().

Hier noch mein Benchmark zum selber Ausprobieren. Natürlich ist das immer ein Szenario und deckt damit nicht jeden Fall ab – ein anderer Benchmark kann ein völlig anderes Ergebnis liefern, ein neuerer Browser andere Werte, etc. Ich habe die Funktionen was Argumente und Verhalten angeht nachgeschrieben, allerdings ist ein 1:1 Vergleich immer schwer und das Szenario (wie bei einem Benchmark üblich) natürlich extrem (10000 Elemente im Array und 1000 Durchgänge).

Das eigentliche Fazit: Gerade bei neuen Methoden wie den JavaScript 1.6+ Array Funktionen, die nicht bei jedem Browser vorhanden sind sollte immer erst geprüft ob sich der Aufwand lohnt, oder ob man auf ‘konservative’ Methoden zurückgreift. Cross-Browser-Kompatibilität erfordert immer Mehraufwand, und dieser wird nur gerechtfertigt wenn unterm Strich ein Mehrwert herauskommt. Und darauf will ich hinaus: Wir Webentwickler werden zwar einige neue Features wie Iteratoren und Generatoren bekommen (Firefox unterstützt diese auch schon bereits) – trotzdem ergibt es oft Sinn, lieber auf Helferfunktionen von Core-Toolset wie Prototype, JQuery oder ExtJS zu setzen, die browserübergreifend die selben Funktionalitäten anbieten. Die ‘neueren’ Methoden sind  a) nicht in jedem Browser vorhanden, und b) evtl. sogar langsamer, oder nur minimal schneller – womit sie derzeit für den Produktiveinsatz ausscheiden.

Ich will hier natürlich keinen Fortschritt aufhalten: Es ist gut, dass sinnvolle Hilfsmethoden wie filter() oder map() Einzug in den Standard finden und ich werde sie sicher auch selbst nutzen wenn Sie verbreitet genug sind. Allerdings sollte man für den Produktiveinsatz eher mit geschärften Bewusstsein an neue (Sprach-)Features wagen.

share save 171 16 JavaScript Performance: Warum nativ nicht immer besser ist.

Low-level memory access in JavaScript: Typed arrays.

Interessante, aber eher unbekannte (da sehr neue) Datentypen in JavaScript  sind der ArrayBuffer und Typed Arrays. Diese Datentypen wurden in erster Linie eingeführt um effektiv auf Binärdaten zugreifen zu können.

Grundlage für alles ist der ArrayBuffer, ein einfacher Datentyp, den man beim Erstellen mitteilt wie viele Bytes er belegen soll. Das besondere ist dass dieser ArrayBuffer an sich keine Möglichkeit besitzt gelesen oder beschrieben zu werden (auch wenn die Spezifikation einen Proposal für eine ‘splice’ Methode hat). Hier kommen die Typed Array Datentypen (oder wie in der Spec: Views) hinzu. Diese ermöglichen es dem Speicher eine logische Aufteilung zu geben, z.B. als ein Array von 32-Bit großen Floats im Falle von Float32Array:

var buffer = new ArrayBuffer(8); // 8 Byte im speicher reservieren
var floatBuffer = new Float32Array(buffer); //floatBuffer ist jetzt ein Array mit 2 elementen (8*8/32 = 2)
floatBuffer[0] = 0.255315; // ab hier gibt es kaum einen Unterschied zu einem normalen js array, ausser dass indexüberlaufe einfach ignoriert werden
floatBuffer[1] = 0.3535;

Der Nutzen ist, dass man mit JavaScript nun effektiv mit binären Daten arbeiten kann. Davor musste man Binärdaten als String darstellen, mit charCodeAt Byteweise auslesen und Datentypen wie Floats und Integers ebenfalls aus Byteblöcken zusammenbauen.

Mich hat allerdings eher interessiert, wie sich die Performance von ‘normalen’ Operationen auf Arrays verhält, wenn man das JavaScript Array Objekt mit dem ArrayBuffer austauscht. Mein Benchmark dafür ist sehr einfach:

for(var i=0;i<size;i++) {
    container[i] = Math.random();
}

var sum = 0;
for(var i=1;i<size;i++) {
sum += container[i];
}
var avg = sum/size;

Ich fülle hier einfach ein Array ‘container’ (welches wahlweise ein ArrayBuffer oder ein Array Objekt ist) mit Zufallswerten und berechne anschliessend den Durchschnitt. Das ganze habe ich auf meinem MacBook Pro 13″ (i5 2,3Ghz) mit ‘size’ von 21 bis 225 einmal im Chrome 14 getestet und einmal im Firefox 6. Die Ergebnisse in bunt (Die Elemente mit 0 ms habe ich mal herausgelassen):

Bildschirmfoto 2011 09 22 um 11.49.24 300x154 Low level memory access in JavaScript: Typed arrays.

Man sieht ganz klar, wie die Performance des internen Arrays ab ca. 65536 Elementen ausreisst (vor allem im Chrome), während das Float32Array recht linear skaliert. Bei sehr großen Datenmengen lohnt es sich also, mal ein Float32Array -wenn vorhanden- auszuprobieren. Einen Nachteil haben die BufferArray Objekte allerdings: Das erstellen ist aufwändiger als bei internen Arrays. Generell sollte man immer die Performance messen und schauen, ob man wirklich einen sinnvollen Geschwindigkeitsbonus durch Typed Arrays bekommt – mein Benchmark hat keinen Anspruch auf Allgemeingültigkeit.

Fazit: JavaScript kann jetzt endlich effektiv mit größeren und binären Datenmengen umgehen. Man muss zwar entscheiden, ob sich der Aufwand lohnt – immerhin muss man, will man kompatibel zu älteren Browsern bleiben, eine Fallback-Variante anbieten. In Kombination mit WebSockets und der File Api eröffnen sich aber ganz neue Möglichkeiten (wie z.B. pdf.js, das PDF direkt in JavaScript rendert).

share save 171 16 Low level memory access in JavaScript: Typed arrays.

MySQL 5.5 ist raus!

Bereits im März haben wir mal über den damals eingeschlagenen Entwicklungsprozess von MySQL gebloggt, der uns gestern zu einer neuen MySQL GA Version verholfen hat. Diese lang erwartete Version bringt uns viele neue Features und vor allem Optimierungen der verbreitetsten Open Source Datenbank.

logo mysql 110x57 MySQL 5.5 ist raus!Viele Benutzer waren oder sind durch den Kauf von SUN Microsystems und damit MySQL durch Oracle verunsichert, wie es mit der Datenbank weitergeht. Ich denke es spricht viel dafür das Oracle auch in Zukunft viel Energie in MySQL und die seit Version 5.5 verwendete Default-StorageEngine InnoDB stecken wird. Warum wird sich der ein oder andere Fragen, da Oracle mit der “großen” Datenbank ja das Schlachtschiff am Markt im Portfolio hat? Die Idee aus meiner Sicht ist jedoch eine andere. Gerade mit MySQL konkurriert das Unternehmen aus Redwood Shoores gegen die vielen kleinen Datenbanken am Markt. Mit MySQL kann man so den PostgreSQL-, Sybase- oder MSSQL-Server Kunden abholen und in den Kundenstamm integrieren. Dafür spricht beispielsweise die erhebliche Performanceoptimierung der Windowsversion, welche ein 15Fache Performancesteierung im Read/Write bringen soll. Neben unzähligen Optimierungen welche im Vergleich zu 5.1 einen deutlich stabileren Eindruck machen ist die semi-synchrone Replikation eines der aus meiner Sicht spannenden Features.

Während die Master-DB in normalen Replikationsumgebungen nichts vom Status der Slave-Datenbanken weiss, bietet die semi-synchrone Replikation die Möglichkeit den Dateneingang im Slave zu verifizieren. Dies hat bei Schreibvorgängen natürlich Einfluss auf die Performance, bringt dem Nutzer jedoch nun bei Bedarf systemübergreifende Transaktionssicherheit. Nach einem konfigurierbaren Timeout schaltet der Master bei Ausfall alles Slaves auf die normale asynchrone Replikation um, um die Verfügbarkeit des Systems weiter zu gewährleisten.

Wer mehr wissen möchte findet im Oracle-Blogpost die Highlights der neuen Version und viele Details auch zur Replikation in den verlinkten Artikeln.

share save 171 16 MySQL 5.5 ist raus!

Performanceboost durch SSD im Notebook

Habe seit ein paar Wochen ein neues Dell Latitude E6500 im Einsatz, welches mit einer SSD-Platte ausgestattet ist.

Ich kann zwar nicht genau sagen, welchen Anteil das an der Gesamtperformance hat, aber der Unterschied zu meiner alten Möhre ist schon enorm. Etwas schnellerer Prozessor, Win7 statt Vista und 4GB RAM statt 2GB vorher, aber ich glaube, dass der Schub durch SSD am deutlichsten spürbar ist. Beim Leistungsindex ist die Platte auch mit 7,3 die am höchsten bewertete Komponente (Grafik 3,4), was auch immer das genau bedeutet.

Ich merk das aber schon deutlich beim Hoch- und Runterfahren, auch Ruhe- oder Standbymodus. Da bin ich früher erstmal nen Kaffee trinken gegangen, jetzt dauert das nur wenige Sekunden. Am längsten noch das Hochfahren mit ca. 25 Sekunden bis zur Anmeldung. Runterfahren 10 Sekunden. Standby 5-10 Sekunden.

Und auch die Applikationen wie z.B. Outlook. Das hat sonst auch ewig gedauert bis die da waren.

Jetzt: Anklicken, Zack und da. Und das ewige Gerappel von der Platte fällt auch weg icon smile Performanceboost durch SSD im Notebook

Also ich hab zwar keine Benchmarks gemacht, aber subjektiv ist das echt ne ganz andere Welt.

Mit 128 GB allerdings auch nicht allzu üppig bemessen, aber für den üblichen Officekram reicht das auch locker aus.

Kann ich wärmstens empfehlen.

share save 171 16 Performanceboost durch SSD im Notebook

Londoner Börse wechselt zu Linux und Solaris

Heise hat gestern gemeldet, dass die Londoner Börse (LSE) von ihrer bestehenden und auf .NET basierenden Handelsplattform auf eine neue Lösung umsteigt. Die neue Plattform wurde von einer Firma in Sri Lanka entwickelt und läuft unter Linux oder Solaris. Interessant ist, dass der Wechsel nicht nur aus Kostengründen erfolgt, sondern auch die bessere Performance der neuen Software eine große Rolle gespielt hat.

Trotzdem scheint der Kostenvorteil sehr groß zu sein, denn für etwa 30 Mio Euro Kaufpreis hat die LSE gleich die komplette Herstellerfirma gekauft, während bei der alten Lösung etwa 65 Mio Euro Kosten angefallen sind – vermutlich nur für Lizenzgebühren.

share save 171 16 Londoner Börse wechselt zu Linux und Solaris

MySQLTuner – Wenn es schnell gehen muss

Informationen zur Optimierung einer MySQL Datenbank gibt es im Web in nahezu endloser Fülle. Auch die vorhandene Lektüre, wie z.B. “High Performance MySQL” ist detailliert und gibt auch Einsteigern nützliche Tipps an die Hand um Engpässe auf dem eigenen Server zu ermitteln und idealerweise zu eliminieren.

mysqltuner logo MySQLTuner   Wenn es schnell gehen mussWer weder die Zeit hat sich intensiv einzuarbeiten, noch diverse Fachbücher zu studieren, dem kann MySQLTuner ein hilfreiches Werkzeug sein. Das Perlscript ermittelt anhand der vorhandenen Statistiken mögliche Bottlenecks und zeigt entsprechende Optimierungspotentiale im Form von Empfehlungen und konkreten Einstellungshinweisen.

Neben der Prüfung verschiedener Hit Ratios errechnet MySQLTuner auch den maximal benötigten Speicher der aktuellen Konfiguration. Hier lassen sich mögliche Probleme bei Nutzung der zugelassenen Connection erkennen und vermeiden.

Installation:

wget http://mysqltuner.com/mysqltuner.pl
chmod +x mysqltuner.pl
./mysqltuner.pl

Output:

 >>  MySQLTuner 1.0.0 - Major Hayden
 >>  Bug reports, feature requests, and downloads at http://mysqltuner.com/
 >>  Run with '--help' for additional options and output filtering

-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.0.51a-24+lenny1
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[--] Data in MyISAM tables: 1G (Tables: 86)
[--] Data in InnoDB tables: 176M (Tables: 120)
[--] Data in MEMORY tables: 124K (Tables: 1)
[!!] Total fragmented tables: 17

-------- Performance Metrics -------------------------------------------------
[--] Up for: 16d 1h 27m 51s (212M q [153.460 qps], 2M conn, TX: 27B, RX: 14B)
[--] Reads / Writes: 50% / 50%
[--] Total buffers: 58.0M global + 2.6M per thread (100 max threads)
[OK] Maximum possible memory usage: 320.5M (15% of installed RAM)
[OK] Slow queries: 0% (100/212M)
[OK] Highest usage of available connections: 36% (36/100)
[OK] Key buffer size / total MyISAM indexes: 16.0M/120.5M
[OK] Key buffer hit rate: 99.8% (63M cached / 99K reads)
[OK] Query cache efficiency: 31.3% (8M cached / 27M selects)
[!!] Query cache prunes per day: 23191
[OK] Sorts requiring temporary tables: 0% (87 temp sorts / 103K sorts)
[!!] Joins performed without indexes: 3446897
[OK] Temporary tables created on disk: 0% (830 on disk / 4M total)
[OK] Thread cache hit rate: 99% (1K created / 2M connections)
[!!] Table cache hit rate: 0% (64 open / 47K opened)
[OK] Open file limit used: 1% (20/1K)
[OK] Table locks acquired immediately: 99% (60M immediate / 60M locks)
[!!] InnoDB data size / buffer pool: 176.7M/8.0M

-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Enable the slow query log to troubleshoot bad queries
    Adjust your join queries to always utilize indexes
    Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
    query_cache_size (> 16M)
    join_buffer_size (> 128.0K, or always use indexes with joins)
    table_cache (> 64)
    innodb_buffer_pool_size (>= 176M)

Beachten sollte man, dass sich nach Änderung von Parametern und Neustart des Servers einige Empfehlungen ändern, die auf Basis von Laufzeitstatistiken ermittelt werden. Es macht also durchaus Sinn, dass System ein paar Stunden mit der neuen Konfiguration zu betreiben, bevor man erneut Rückschlüsse aus den gewonnenen Informationen zieht.

share save 171 16 MySQLTuner   Wenn es schnell gehen muss

Serie High Performance Websites – Zusammenfassung

Teil 6 von 6 in der Blogserie High Performance Websites

serie Serie High Performance Websites   ZusammenfassungZusammenfassung der Serie über High Performance Websites.

In dieser Artikelserie haben wir versucht einen kurzen Einblick in die Optimierung von Server, Sourcecode und Infrastruktur in Bezug auf Performance zu geben.

Für Feedback oder Anregungen sind wir selbstverständlich jederzeit offen und freuen uns über jede Kontaktaufnahme.

share save 171 16 Serie High Performance Websites   Zusammenfassung

Serie High Performance Websites – Teil 5: letztes Feintuning

Teil 5 von 6 in der Blogserie High Performance Websites

high performance serie4 Serie High Performance Websites   Teil 5: letztes FeintuningDieser vorerst finale Teil befasst sich mit den restlichen Serverseitigen Themen Redirects und Keep-Alive. Zusätzlich wird auf DNS und das DNS Cacheverhalten des Browsers eingegangen.

Für die Performance von Webseiten hat DNS ausschließlich beim erstmaligen Aufruf Einfluss. Hier ist zu beachten das der DNS Server ihres ISP typischerweise 10-200 Millisekunden braucht um eine Namensauflösung durchzuführen. Nach der Erstanfrage wird der DNS Eintrag sowohl im Betriebssystem als auch im Browser gecached um erneute Anfragen zu vermeiden. Wie lange der bereits erfragte Eintrag zwischengespeichert wird gibt in erster Linie die TTL (Time-To-Live) in der DNS Zone an, desweiteren ist in den Browsern hinterlegt wie lange der DNS Cache zusätzlich zur TTL Einträge speichern soll. Dies kann bedeuten das trotz bereits abgelaufener TTL ein DNS Eintrag im Browser noch durch den Cache vorgehalten wird.

In Summe kann festgehalten werden das es sinnvoll ist die Verwendung unterschiedlicher Hostnamen auf ein minimum zu reduzieren um die durch DNS Anfragen entstehende Latenz beim erstmaligen Laden der Seite zu reduzieren.

In den vorherigen Kapiteln wurde vieles unternommen um die Ladezeit für den Benutzer so gering wie möglich zu halten. Genau das Gegenteil verursachen leider verwendete Redirects, wird bei der ersten HTTP Anfrage ein Redirect vom Server erwidert folgt daraus ein erneuter (also zusätzlicher) HTTP Request. Dieses Verhalten verzögert das Laden der eigentlichen Seite und sollte vermieden werden.

Ziel ist also Redirects wenn möglich zu verhindern oder sehr eingeschränkt zu verwenden.

Zur weiteren Optimierung sollte Keep-Alive serverseitig aktiviert werden, hier werden vom Browser bereits offene TCP Verbindungen für einen definierten Zeitraum wiederverwendet. Dieser Mechanismus spart zusätzlich Zeit für den eigentlichen TCP Verbindungsaufbau. Der Server und Browser signalisieren beim initiieren der Verbindung im “Connection” Header ob Keep-Alive Verbindungen erlaubt sind. Zusätzlich zu Keep-Alive wird unter HTTP/1.1 Pipelining zur Verfügung gestellt um die Verbindungsgeschwindigkeit zu erhöhen. Hier werden mehrere Anfragen über einen Socket übermittelt ohne vorher auf eine Antwort des Servers warten zu müssen.

In Apache wird Keep-Alive durch die folgenden Direktiven aktiviert.

Keep-Alive on

share save 171 16 Serie High Performance Websites   Teil 5: letztes Feintuning

Serie High Performance Websites – Teil 4: Weniger ist Mehr !

Teil 4 von 6 in der Blogserie High Performance Websites

high performance serie3 Serie High Performance Websites   Teil 4: Weniger ist Mehr !Ein weiterer wichtiger Punkt bei der Optimierung ist das Thema Kompression, hierbei werden sämtliche noch komprimierbaren Inhalte (HTML, CSS, JavaScript, …) geschrumpft und so in einer verkleinerten Version ausgeliefert.

Die durchschnittliche Einsparung durch Komprimierung beträgt bis zu 70% was bedeutet das nur 30% des ursprünglichen Dateiinhaltes übertragen werden müssen. In den meisten Setups wird “gzip” für die Verkleinerung der ܜbertragungmenge verwendet, gzip bietet hier eine bessere Komprimierungsrate als “deflate”.

Um die Komprimierung in Apache zu aktivieren muss mod_deflate geladen werden, zusätzlich zum laden des Moduls muss in der VirtualHost (oder globalen) Konfiguration die Kompression aktiviert werden.

AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/x-javascript

Zusätzlich lässt sich mit dem Parameter DeflateCompressionLevel der Komprimierungsgrad festlegen, die Grundeinstellung ist hier meist ausreichend.

Einige ältere Browserversionen unterstützen leider keine Kompression, deswegen sollten zusätzlich folgende Einstellungen hinterlegt werden um auch diesen “Exoten” Zugang zur Webpräsenz zu ermöglichen.

BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

Durch die nun gesetzten Einstellungen werden sämtliche “textuellen” Inhalten wie HTML/CSS oder JS ab jetzt komprimiert übertragen. Im nächsten Teil wird nun noch angeführt wie mittels DNS, Keepalive und der vermeidung von Redirects noch zusätzlich Ladezeit verkürzt werden kann.

Analog hierzu ist die Konfiguration unter Lighttpd, das “deflate” Modul ist vollständig unter http://redmine.lighttpd.net/projects/lighttpd/wiki/Mod_Deflate dokumentiert. Die Einrichtung ist hier denkbar einfach sofern Lighttpd mit Kompressionsunterstützung übersetzt wurde (sollte in allen Distributionspaketen Standard sein).

share save 171 16 Serie High Performance Websites   Teil 4: Weniger ist Mehr !

Serie High Performance Websites – Teil 3: Cachen erlaubt !

Teil 3 von 6 in der Blogserie High Performance Websites

high performance serie2 Serie High Performance Websites   Teil 3: Cachen erlaubt !Nachdem im vorherigen Teil die HTTP-Requests auf ein minimum reduziert wurden ist es nun an der Zeit den Client das zwischenspeichern von Inhalten auf eine besitmmte Zeit hin zu erlauben.

Hierfür werden sog. Expires-Header serverseitig konfiguriert. Die dadurch in den HTTP-Response gesetzten  ”Expires” und “Cache-Control” Header werden bei der Auslieferung jedes Contentelements übertragen. Definiert wird der Expires-Header auf Basis von Dateinamen oder Pfaden in der abgerufenen URL. Um die Expires in Apache nutzen zu können muss mod_expires aktiviert sein.

Für Lighttpd ist eine passende Anleitung unter http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModExpire zu finden.

Zusätzlich ist es notwendig in der Konfiguration des entsprechenden VirtualHost’s folgende definitionen vorzunehmen:

<IfModule mod_expires.c>
ExpiresActive on
ExpiresByType image/gif "access plus 10 years"
ExpiresByType image/jpeg "access plus 10 years"
ExpiresByType image/png "access plus 10 years"
ExpiresByType text/css "access plus 2 years"
ExpiresByType text/js "access plus 2 years"
ExpiresByType text/javascript "access plus 2 years"
ExpiresByType application/javascript "access plus 2 years"
ExpiresByType application/x-javascript "access plus 2 years"
</IfModule>

Hier wird für die genannten Elemente jeweils eine Ablaufzeit von 10 bzw. 2 Jahren definiert, was den anfragenden Browser dazu bringt das geladene Element für 10 bzw. 2 Jahre im Browsercache zu halten und nicht erneut abzufragen.

Zusätzlich kann noch ein genereller Expire mittels

ExpiresDefault ”access plus 1 days”

gesetzt werden.

Durch dieses Verhalten ergibt sich allerdings ein neues Problem, beispielsweise kann es sein das sich innerhalb dieser 2 Jahre das Stylesheet verändert. In diesem Fall würde der Browser das veränderte CSS durch die ihm Bekannte “Cache-Halbwertszeit” von 2 Jahren nicht neu laden und die Änderung würde nicht angezeigt. Um dieses Problem zu verhindert sollte eine Versionierung der “halbstatischen” Elemente durchgeführt werden, aus “style.css” wird so “style-20090101-001.css”.

Ändert sich nun das Stylesheet auf “style-20090101-002.css” wird der Sourcecode der HTML Seite um den Namen des CSS angepasst und der Browser läd automatisiert die neue Version da ihm das “neue” Inhaltselement nicht im Cache bekannt ist.

share save 171 16 Serie High Performance Websites   Teil 3: Cachen erlaubt !