Cache ([[1]) bezeichnet in der Informationstechnik einen schnellen Pufferspeicher, der (wiederholte) Zugriffe auf vergleichsweise langsame Datenspeicher oder aufwendige Neuberechnungen zu vermeiden hilft. Daten, die bereits einmal geladen oder generiert wurden, verbleiben im Cache, so dass sie bei späterem Bedarf schneller aus diesem abgerufen werden können. Auch können Daten, die vermutlich bald benötigt werden, vorab vom Hintergrundmedium abgerufen und vorerst im Cache bereitgestellt werden (read-ahead).
], auch [ ]Caches können als Hardwarestruktur (beispielsweise als Hauptspeicherchips) oder Softwarestruktur (beispielsweise als temporäre Dateien oder reservierter Speicherplatz) ausgebildet sein.
Das Konzept eines schnellen Zwischenspeichers, wie es hier beschrieben ist, wurde erstmals im April 1965 von M. V. Wilkes vorgestellt.[2]
Cache ist ein Lehnwort, das in diesem Zusammenhang vermutlich erstmals bei IBM in Amerika aus dem Französischen entnommen wurde. Zumindest wird es bereits 1973 in einem Aufsatz von K. R. Kaplan, einem Mitarbeiter des Department of Computer Science am Livingston College der Rutgers University in New Jersey, verwendet.[3] Seinen Ursprung hat es im französischen cache, das eigentlich die Bedeutung Versteck hat.[4][5] Der Name verdeutlicht den Umstand, dass dem Verwender in der Regel der Cache und seine Ersatzfunktion für das angesprochene Hintergrundmedium verborgen bleibt. Wer das Hintergrundmedium verwendet, muss Größe oder Funktionsweise des Caches prinzipiell nicht kennen, denn der Cache wird nicht direkt angesprochen. Der Verwender „spricht das Hintergrundmedium an“, stattdessen „antwortet“ jedoch der Cache – genau auf die Art und Weise, wie auch das Hintergrundmedium geantwortet, also Daten geliefert hätte. Wegen der Unsichtbarkeit dieser zwischengeschalteten Einheit spricht man auch von Transparenz. Praktisch ist er eine gespiegelte Ressource, die stellvertretend für das Original sehr schnell reagiert.
Greifen außer dem den Cache verwendenden Gerät noch weitere auf das Hintergrundmedium zu, so kann es zu Inkonsistenzen kommen. Um auf ein identisches Datenabbild zugreifen zu können, ist es notwendig, vor dem Zugriff die Änderungen des Caches in das Hintergrundmedium zu übernehmen. Cachestrategien wie Write-Through oder Write-Back sind hier praktikabel. Im Extremfall muss ein kompletter „Cache Flush“ erfolgen.
Außerdem muss ggf. der Cache informiert werden, dass sich Daten auf dem Hintergrundmedium geändert haben und sein Inhalt nicht mehr gültig ist. Stellt die Cachelogik das nicht sicher, so ergibt sich als Nachteil, dass inzwischen im Hintergrundmedium oder im Rechenprogramm erfolgte Änderungen nicht erkannt werden. Bei Verdacht auf Änderungen, oder um sicherzugehen, dass der aktuelle Stand berücksichtigt wird, muss der Benutzer explizit eine Cache-Aktualisierung veranlassen.
Die Ziele beim Einsatz eines Caches sind eine Verringerung der Zugriffszeit und/oder eine Verringerung der Anzahl der Zugriffe auf ein langsames Hintergrundmedium. Das bedeutet insbesondere, dass sich der Einsatz von Caches nur dort lohnt, wo die Zugriffszeit auch signifikanten Einfluss auf die Gesamtleistung hat. Während das z. B. beim Prozessorcache der meisten (skalaren) Mikroprozessoren der Fall ist, trifft es nicht auf Vektorrechner zu, wo die Zugriffszeit eine untergeordnete Rolle spielt. Deswegen wird dort üblicherweise auf Caches verzichtet, weil diese keinen oder nur wenig Nutzen bringen.
Ein weiterer wichtiger Effekt beim Einsatz von Caches ist die Verringerung der notwendigen Datenübertragungsrate an die Anbindung des Hintergrundmediums (siehe z. B. Speicherhierarchie); das Hintergrundmedium kann also „langsamer angebunden“ werden, was z. B. geringere Kosten ergeben kann. Weil oft der Großteil der Anfragen vom Cache beantwortet werden kann („Cache Hit“, s. u.), sinkt die Anzahl der Zugriffe und damit die notwendige Datenübertragungsrate. Zum Beispiel würde ein moderner Mikroprozessor ohne Cache selbst mit sehr kleiner Zugriffszeit des Hauptspeichers dadurch ausgebremst, dass nicht genügend Speicherbandbreite zur Verfügung steht, weil durch den Wegfall des Caches die Anzahl der Zugriffe auf den Hauptspeicher und damit die Anforderung an die Speicherbandbreite stark zunehmen würde.
Bei CPUs kann der Einsatz von Caches somit zum Verringern des Von-Neumann-Flaschenhalses der Von-Neumann-Architektur beitragen. Die Ausführungsgeschwindigkeit von Programmen kann dadurch im Mittel enorm gesteigert werden.
Ein Nachteil von Caches ist das schlecht vorhersagbare Zeitverhalten, da die Ausführungszeit eines Zugriffs aufgrund von Cache-Misses nicht immer konstant ist. Sind die Daten nicht im Cache, muss der Zugreifende warten, bis sie von dem langsamen Hintergrundmedium geladen wurden. Bei Prozessoren geschieht das oft bei Zugriffen auf bisher noch nicht verwendete Daten oder beim Laden des nächsten Programmbefehls bei (weiten) Sprüngen.
Da es technisch aufwändig und damit meist wirtschaftlich nicht sinnvoll ist, einen Cache zu bauen, der sowohl groß als auch schnell ist, kann man mehrere Caches verwenden – z. B. einen kleinen schnellen und einen deutlich größeren, jedoch etwas langsameren Cache (der aber immer noch viel schneller ist als der zu cachende Hintergrundspeicher). Damit kann man die konkurrierenden Ziele von geringer Zugriffszeit und großem Cacheumfang gemeinsam realisieren. Das ist wichtig für die Hit Rate.
Existieren mehrere Caches, so bilden diese eine Cachehierarchie, die Teil der Speicherhierarchie ist. Die einzelnen Caches werden nach ihrer Hierarchieebene (engl. level) durchnummeriert, also Level‑1 bis Level‑n oder kurz L1, L2 usw. Je niedriger die Nummer, desto näher liegt der Cache am schnellen „Benutzer“; die niedrigste Nummer bezeichnet daher den Cache mit der schnellsten Zugriffszeit, dieser wird als erstes durchsucht. Enthält der L1-Cache die benötigten Daten nicht, wird der (meist etwas langsamere, aber größere) L2-Cache durchsucht usw. Das geschieht solange, bis die Daten entweder in einer Cacheebene gefunden (ein „cache Hit“, s. u.) oder alle Caches ohne Erfolg durchsucht wurden (ein „Cache Miss“, s. u.). In letzterem Fall muss auf den langsamen Hintergrundspeicher zugegriffen werden.
Tritt ein Cache Hit z. B. im L3-Cache auf, so werden die angeforderten Daten dem Zugreifer geliefert und zugleich in den L1-Cache übernommen; dafür muss dort eine Cache-Line weichen, die in den L2-Cache „absinkt“.
Exklusive Cache-Hierarchien erzeugen deutlich mehr Datenverkehr zwischen den Caches. Dafür können so viele Cache-Lines bereitgehalten werden wie die Summe von L1-, L2- und L3-Cache-Größe, während beim inklusiven Cache nur die L3-Cache-Größe maßgebend ist.
Im Hardwarebereich weisen vor allem moderne CPUs zwei oder drei Cacheebenen auf; sonstige Geräte besitzen meist nur eine Cacheebene. Im Softwarebereich wird meist nur eine Cacheebene benutzt, eine prominente Ausnahme bilden Webbrowser, die zwei Ebenen nutzen (Arbeitsspeicher und Festplattenlaufwerk).
Um den Nutzen des meist um mehrere Zehnerpotenzen kleineren Caches im Vergleich zum Hintergrundspeicher zu maximieren, werden bei der Funktionsweise und Organisation eines Caches die Lokalitätseigenschaften der Zugriffsmuster ausgenutzt. Beobachtet man beispielsweise die Aktivität eines laufenden Programms auf einem Prozessor über ein kurzes Zeitintervall, so stellt man fest, dass wiederholt auf wenige und „immer dieselben“ kleinen Speicherbereiche (z. B. Code innerhalb von Schleifen, Steuervariablen, lokale Variablen und Prozedurparameter) zugegriffen wird. Deshalb können bereits kleine Caches mit einigen Kibibytes sehr wirksam sein.
Verarbeitet ein Algorithmus jedoch ständig neue Daten (z. B. Streaming-Daten), kann ein Cache keine Beschleunigung durch Mehrfach-Zugriffe bewirken, allenfalls geringfügig durch read-ahead.
Da Caches schnell sein sollen, verwendet man für sie meist eine andere (schnellere) Speichertechnologie als für den zu cachenden Speicher (zum Beispiel SRAM gegenüber DRAM, DRAM gegenüber Magnetscheibe usw.). Daher sind Caches meist wesentlich teurer in Bezug auf das Preis-Bit-Verhältnis, weshalb sie deutlich kleiner ausgelegt werden. Das führt dazu, dass ein Cache nicht alle Daten gleichzeitig vorrätig haben kann. Um das Problem zu lösen, welche Daten im Cache gehalten werden sollen, werden die Lokalitätseigenschaften der Zugriffe ausgenutzt:
Zeitliche (temporale) Lokalität
Räumliche (spatiale) Lokalität
Wegen der räumlichen Lokalität speichern Caches nicht einzelne Bytes, sondern Datenblöcke („Cacheblock“ oder manchmal auch „Cache-Line“ genannt). Zusätzlich erleichtert das die Implementierung und verringert Speicheroverhead, da man nicht pro Datenbyte eine Adresse speichern muss, sondern nur für jeden Cacheblock. Die Wahl der Blockgröße ist ein wichtiger Designparameter für einen Cache, der die Leistung stark beeinflussen kann.
Ein Cache besteht aus einer (meist) festen Anzahl Einträgen, jeder Eintrag besteht aus:
Cache-Line
Address-Tag
Dirty-Tags
Valid-Tags
LRU-Tags
Siehe auch unten #Einträge im Cache.
Eine Cache-Line ist die kleinste Verwaltungseinheit innerhalb des Caches von Prozessoren. Es handelt sich dabei um eine Kopie eines Speicherbereichs. Die Zugriffe vom Cache-Speicher zum Hauptprozessor oder zum Hauptspeicher erfolgen somit in einem einzigen, blockweisen Transfer. Die Größe einer Cache-Line beträgt 16 Bytes (Intel 80486), 32 Bytes (Intel Pentium bis Pentium III) und 64 Bytes (Intel Pentium 4 bis aktuelle Intel-Core-i-/AMD-Ryzen-Prozessoren).[7] Die Minimallänge ergibt sich aus der Speicher-Busbreite multipliziert mit der Prefetch-Tiefe des Hauptspeichers und liegt heutzutage bei 64 oder 128 Bytes.[8]
Im Nachfolgenden wird davon ausgegangen, dass Cache-Lines immer nur von Adressen gelesen und geschrieben werden, deren Adresse durch die (Byte-)Länge der Cache-Line teilbar ist.
Eine Cache-Line sei 64 Bytes groß. Es sei festgelegt, dass Daten nur gelesen und geschrieben werden können mit Startadressen z. B. 0, 64, 128, 192, 256, … Das Hintergrundmedium ist also aufgeteilt in Blöcke, die gerade so groß wie eine Cache-Line sind.
Dann muss in den Adress-Tags nicht mehr die gesamte (Start-)Adresse der Daten gespeichert werden, sondern nur noch, der wievielte Datenblock auf dem Hintergrundmedium gecachet ist. Durch die Wahl passender Zahlen (Zweierpotenzen) im Binärsystem lassen sich so die Tags platzsparender speichern; das beschleunigt das Prüfen, ob eine angefragte Adresse im Cache enthalten ist.
Die Blöcke (Cache-Lines) eines Caches können in so genannte Sätze zusammengefasst werden. Für eine bestimmte Adresse ist dann immer nur einer der Sätze zuständig. Innerhalb eines Satzes bedienen alle Blöcke also nur einen Teil aller vorhandenen Adressen. Im Folgenden stehe die Variable für die Gesamtanzahl der Cacheblöcke und für die Anzahl der Blöcke pro Satz, die so genannte Assoziativität. Dann besteht der Cache also aus Sätzen.
Organisation | Anzahl der Sätze | Assoziativität |
---|---|---|
DM | 1 | |
FA | 1 | () |
SA |
Je nachdem, wie stark man diese Aufteilung vornimmt, spricht man von einer der drei Cache-Organisationsarten:
Direkt abgebildet (engl. direct mapped, kurz DM)
Vollassoziativ (engl. fully associative, kurz FA)
Satzassoziativ bzw. mengenassoziativ (engl. set associative, kurz SA)
Die ersten beiden sind ein Spezialfall des satzassoziativen Caches. Der direkt abgebildete und der vollassoziative Cache lassen sich somit vom satzassoziativen Cache ableiten: n=1 führt zu einem direkt abgebildeten Cache, n=m zu einem vollassoziativen Cache.
Die wesentlichen Größen eines Caches sind:
Der Cache besteht, unabhängig vom Aufbau, aus 64 KiB/64 Byte = 1024 Cache-Zeilen
Vollassoziativer Cache
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Länge Adress-Tag | Byte-Position |
Es gibt eine Cache-Gruppe, die alle 1024 Cache-Zeilen umfasst. Jedes Hauptspeicher-Datenwort kann in jeder beliebigen der 1024 Cache-Zeilen der einen Cache-Gruppe gespeichert werden. Es sind 1024 Komparatoren erforderlich, die log2(4 GiB/64 Byte) = log2(4 GiB)-log2(64 Byte) bits = 32-6 = 26 bits vergleichen müssen. An jeder Cache-Zeile hängen diese 26 Bit als Adress-Tag. Hardware-Aufwand:
Direct Mapped-Cache / Einfach- oder nicht assoziativer Cache
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Länge Adress-Tag | benutzte Cache-Gruppe | Byte-Position |
Es gibt 1024 Cache-Gruppen mit je einer Cache-Zeile. Jedes Hauptspeicher-Datenwort kann nur in dieser zu seiner Adresse gehörenden Cache-Zeile gespeichert werden. Die Cache-Gruppe ergibt sich aus den Bit 15 bis 6 der Adresse. Es ist nur ein Komparator erforderlich, der log2(4 GiB)-log2(64 KiB) bits = 16 bits vergleichen muss. An jeder Cache-Zeile hängen diese 16 Bit als Adress-Tag. Hardware-Aufwand:
Zweifach assoziativer Cache
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Länge Adress-Tag | benutzte Cache-Gruppe | Byte-Position |
Es gibt 512 Cache-Gruppen mit je zwei Cache-Zeilen. Jedes Hauptspeicher-Datenwort kann in einer der beiden zu seiner Adresse gehörenden Cache-Zeilen gespeichert werden. Die Cache-Gruppe ergibt sich aus den Bit 14 bis 6 der Adresse. Es sind zwei Komparatoren erforderlich, die log2(4 GiB)-log2(64 KiB)+1 bits = 17 bits vergleichen müssen. An jeder Cache-Zeile hängen diese 17 Bit als Adress-Tag. Hardware-Aufwand:
2^n-fach assoziativer Cache
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Länge Adress-Tag | benutzte Cache-Gruppe | Byte-Position |
Es gibt 1024/2^n Cache-Gruppen mit je 2^n Cache-Zeilen. Jedes Hauptspeicher-Datenwort kann in einer der 2^n zu seiner Adresse gehörenden Cache-Zeilen gespeichert werden. Die Cache-Gruppe ergibt sich aus den Bit 15-(n-1) bis 6 der Adresse. Es sind 2^n Komparatoren erforderlich, die log2(4 GiB)-log2(64 KiB)+n bits = 16+(n-1) bits vergleichen müssen. An jeder Cache-Zeile hängen diese 16+(n-1) Bit als Adress-Tag. Hardware-Aufwand:
Den Vorgang, dass die Daten einer Anfrage an einen Cache in selbigem vorrätig sind, bezeichnet man als „Cache Hit“ (dt. Cachetreffer), den umgekehrten Fall als „Cache Miss“ (dt. „Cache-Verfehlen“).
Um quantitative Maßzahlen für die Bewertung der Effizienz eines Caches zu erhalten, definiert man zwei Größen:
Hit Rate
Miss Rate
Drei Arten von Cache Misses werden unterschieden:
Capacity
Conflict
Compulsory
Diese drei Typen bezeichnet man auch kurz als „Die drei C“. In Multiprozessorsystemen kann beim Einsatz eines Cache-Kohärenz-Protokolls vom Typ Write-Invalidate noch ein viertes „C“ hinzukommen, nämlich ein „Coherency Miss“: Wenn durch das Schreiben eines Prozessors in einen Cacheblock der gleiche Block im Cache eines zweiten Prozessors hinausgeworfen werden muss, so führt der Zugriff des zweiten Prozessors auf eine Adresse, die durch diesen entfernten Cacheblock abgedeckt war, zu einem Coherency Miss.
Bei der Verwaltung des Caches ist es sinnvoll, immer nur die Blöcke im Cache zu halten, auf die auch häufig zugegriffen wird. Zu diesem Zweck gibt es verschiedene Ersetzungsstrategien. Eine häufig verwendete Variante ist dabei die LRU-Strategie (engl. least recently used), bei welcher immer der Block ausgetauscht wird, auf den am längsten nicht mehr zugegriffen wurde. Moderne Prozessoren (z. B. der AMD Athlon) implementieren meist eine Pseudo-LRU-Ersetzungsstrategie, die fast wie echtes LRU arbeitet, aber leichter in Hardware zu implementieren ist.
FIFO (First In First Out)
First In – First Out (FIFO)
Least recently used (LRU)
Least frequently used (LFU)
Random
CLOCK
Optimal
Bei einem Schreibzugriff auf einen Block, der im Cache vorhanden ist, gibt es prinzipiell zwei Möglichkeiten:
Zurückkopieren (write-back)
Durchgängiges Schreiben (write-through)
Analog zu Obigem gibt es bei einem Schreibzugriff auf einen Block, der nicht im Cache vorhanden ist, prinzipiell ebenso zwei Möglichkeiten:
write-allocate
non-write-allocate
Einige Befehlssätze enthalten Befehle, die es dem Programmierer ermöglichen, explizit anzugeben, ob zu schreibende Daten am Cache vorbeizuschreiben sind.
Normalerweise wird entweder die Kombination write-back mit write-allocate oder write-through mit non-write-allocate verwendet. Die erste Kombination hat den Vorteil, dass aufeinander folgende Schreibzugriffe auf denselben Block (Lokalitätsprinzip) komplett im Cache abgewickelt werden (bis auf den ersten Miss). Dies gibt im zweiten Fall keinen Vorteil, da sowieso jeder Schreibzugriff zum Hauptspeicher muss, weshalb die Kombination write-through mit write-allocate eher unüblich ist.[9]
Ein Cache Flush („Pufferspeicher-Leerung“) bewirkt das komplette Zurückschreiben des Cacheinhaltes in den Hintergrundspeicher. Dabei bleibt der Cacheinhalt meist unangetastet. Ein solches Vorgehen ist nötig, um die Konsistenz zwischen Cache und Hintergrundspeicher wiederherzustellen. Notwendig ist das zum Beispiel immer dann, wenn Daten aus dem Hauptspeicher von externen Geräten benötigt werden, unter anderem bei Multiprozessor-Kommunikation oder bei der Übergabe eines als Ausgabepuffer benutzten Teils des Hauptspeichers an den DMA-Controller.
Für jeden Cacheblock wird im Cache folgendes gespeichert:
Ein Cache ist „heiß“, wenn er optimal arbeitet, also gefüllt ist und nur wenige Cache Misses hat; ist das nicht der Fall, gilt der Cache als „kalt“. Nach Inbetriebnahme ist ein Cache zunächst kalt, da er noch keine Daten enthält und häufig zeitraubend Daten nachladen muss, und wärmt sich dann zunehmend auf, da die zwischengelagerten Daten immer mehr den angeforderten entsprechen und weniger Nachladen erforderlich ist. Im Idealzustand werden Datenzugriffe fast ausschließlich aus dem Cache bedient und das Nachladen kann vernachlässigt werden.
Bei Hauptprozessoren kann der Cache direkt im Prozessor integriert oder extern auf der Hauptplatine (früher weiter verbreitet, heute eher untypisch) platziert sein. Oft gibt es mehrere Ebenen (Levels), die aufeinander aufbauen. Kleinere Level sind dabei typischerweise schneller, haben aber aus Kostengründen eine geringere Größe. Je nach Ort des Caches arbeitet dieser mit unterschiedlichen Taktfrequenzen: Der L1 (Level 1, am nächsten an der CPU) ist fast immer direkt im Prozessor (d. h. auf dem Die) integriert und arbeitet daher mit dem vollen Prozessortakt – also u. U. mehreren Gigahertz. Ein externer Cache hingegen wird oft nur mit einigen hundert Megahertz getaktet.
Aktuelle Prozessorarchitekturen (zum Beispiel AMD Zen 4, Intel Ice Lake, IBM Power10)[7] besitzen überwiegend drei Cache-Level: L1, L2 und L3. Gängige Größen für L1-Caches sind 4 bis 320 KiB pro Prozessorkern (meist gibt es einen für Daten und einen für Befehle), der L2-Cache ist 64 KiB bis 32.768 KiB[10] (meist ebenfalls pro Kern), der L3-Cache 2 bis 768 MiB[11] (für alle Kerne gemeinsam). Prozessorcache als Extra-Chip auf der Hauptplatine wird heute nicht mehr gebaut, als Extra-Die im selben Chip-Gehäuse (siehe Multi-Chip-Modul) nur noch selten.
In jedem Fall ist eine Protokollierung erforderlich, um die Kohärenz der Daten (z. B. zwischen Caches und Hauptspeicher) sicherzustellen. Dazu dienen Flags, die einen Speicherbereich (typischerweise eine ganze line von 64 Byte) als „dirty“, also geändert, markieren (s. o. bei Schreibstrategie). Das Problem verschärft sich bei mehreren Cache-Levels und mehreren Prozessoren oder Prozessorkernen.
Die Cachekonsistenz ist sowohl bei mehreren aktiven Geräten auf dem Datenbus, als auch bei mehreren zusammengeschalteten Prozessoren (Mehrprozessorsysteme) zu beachten.
Bei Mehrprozessorsystemen unterscheidet man unter anderem nach flynnscher Klassifikation zwischen SIMD- und MIMD-Strukturen (Single/Multiple Instruction – Multiple Data). Bei MIMD-Systemen ist die Wahrscheinlichkeit hoch, dass verschiedene Prozessoren auf verschiedene Speicherbereiche zugreifen, bei SIMD dagegen kleiner. Danach lässt sich die Cache-Konfiguration einstellen.
Moderne Prozessoren haben getrennte L1-Caches für Programme und Daten (Lese- und Schreibcache), teilweise ist das auch noch beim L2 der Fall (Intel Itanium 2). Man spricht hier von einer Harvard-Architektur. Das hat den Vorteil, dass man für die unterschiedlichen Zugriffsmuster für das Laden von Programmcode und Daten unterschiedliche Cachedesigns verwenden kann. Außerdem kann man bei getrennten Caches diese räumlich besser zu den jeweiligen Einheiten auf dem Prozessor-Die platzieren und damit die kritischen Pfade beim Prozessorlayout verkürzen. Des Weiteren können Instruktionen und Daten gleichzeitig gelesen/geschrieben werden, wodurch der Von-Neumann-Flaschenhals weiter verringert werden kann. Ein Nachteil ist, dass selbstmodifizierender Code gesondert behandelt werden muss, was seine Ausführung stark verlangsamt. Allerdings wird diese Technik aus Sicherheitsgründen und weil sie oft schwer verständlich, schwer prüfbar und daher nur schlecht zu warten ist, heute ohnehin nur noch sehr selten verwendet.
Bei Festplattenlaufwerken befindet sich der Cache auf der Steuerplatine (siehe Festplattencache) oder einer separaten Platine, dem Host-Bus-Adapter.
Die Größe beträgt bei aktuellen Festplatten – je nach vom Hersteller vorgesehenen Einsatzzweck der Festplatte – zwischen 8 und 256 MiB.[7]
Die meisten optischen Laufwerke besitzen Caches, um die oft im dreistelligen Millisekundenbereich liegenden Zugriffszeiten und Schwankungen im Datenstrom (z. B. durch Synchronisierungsprobleme) aufzufangen.
Caches können auch bei Software genutzt werden, dabei ist dasselbe Prinzip wie bei der Hardwareimplementierung gemeint: Daten werden für einen schnelleren Zugriff auf ein schnelleres Medium zwischengespeichert.
Beispiele: Festplattencache (vom Betriebssystem verwaltet)
Anwendungsdaten (Memoisation)
Software-Caches, welche die Festplatte als schnelleres Medium verwenden, werden meist in Form von temporären Dateien angelegt.
Man spricht auch von Caching, wenn ein Betriebssystem gewisse Ressourcen – wie z. B. Programmbibliotheken oder Schriftarten – vorerst im Arbeitsspeicher belässt, obwohl sie nach Ende ihrer Benutzung nicht mehr gebraucht werden. Solange kein Speichermangel herrscht, können sie im Arbeitsspeicher verbleiben, um dann ohne Nachladen von der Festplatte sofort zur Verfügung zu stehen, wenn sie wieder gebraucht werden. Wenn allerdings die Speicherverwaltung des Betriebssystems einen Speichermangel feststellt, werden diese Ressourcen als erste gelöscht.
Der Suchmaschinen-Cache ist der Lesecache einer Suchmaschine. Eine Suchmaschine besitzt drei Kernkomponenten:
Die Inhalte aller Webseiten, die die Suchmaschine als Basisdaten für Benutzeranfragen berücksichtigt, werden im Suchmaschinen-Cache zwischengespeichert. Die Server einer Suchmaschine können nicht für jede Abfrage jede Webseite in Echtzeit auf die aktuellsten Inhalte durchsuchen; stattdessen wird in einem Index über dem Cache gesucht.
Im Allgemeinen kann ein Webseiten-Betreiber Änderungen seiner Webseiten an die Suchmaschine melden, dann fragt der Webcrawler die Seite baldmöglichst erneut ab; ansonsten prüft der Webcrawler jede Webseite in regelmäßigen Abständen – die Cache-Inhalte können also veraltet sein. Eine Webseite kann dem Crawler einen Hinweis geben, wie häufig sie sich im Allgemeinen ändert. Suchmaschinen gehen mit dieser Information mitunter verschieden um.
Die in Deutschland verbreitetste Suchmaschine ist Google; deren Cache-, Indizier- und Suchstrategien wird daher besonders hohes Interesse zuteil. Die Webcrawler-Frequenz, mit der Webseiten geprüft werden, liegt bei Google bei den meisten Webseiten zwischen einer und vier Wochen („[…] Inhalt wird in der Regel alle 7 Tage aktualisiert“[12]). Gemeldete Webseiten untersucht der sogenannte Googlebot.
Im Domain Name System finden Caches Anwendung, welche die Ergebnisse einer Namensauflösung in einem lokalen Cache vorübergehend zwischenspeichern. Folgende identische DNS-Anfragen können aus dem Cache bedient werden ohne den Nameserver erneut anfragen zu müssen, wodurch die Performance erhöht wird. Bei DNS befinden sich in der Regel Namensserver, Cache und Anwendung auf verschiedenen über das Internet verbundenen Systemen.