Begriff
Memoization
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Ein kompliziertes Wort für "Notizzettel schreiben" (Memo). Wenn eine Computer-Funktion sehr teuer ist (z. B. lange rechnet), ist es dumm, sie zweimal mit der gleichen Frage aufzurufen. Memoization bedeutet: Die Funktion merkt sich ihre Antworten. "Hat mich jemand schon mal mit '5' gefragt? Ja! Damals war die Antwort '25'. Hier, nimm '25', ich rechne nicht nochmal." Es ist eine spezielle Form von Caching für Funktionen.
Merksatz: Eine Optimierungstechnik, bei der Ergebnisse teurer Funktionsaufrufe gespeichert werden, um bei gleichen Eingaben das Ergebnis sofort zurückzugeben.
In React (JavaScript): useMemo.
Es verhindert, dass deine ganze Webseite neu berechnet wird, nur weil du einen Button geklickt hast.
"Wenn sich die Produktliste nicht geändert hat, zeichne die alte Liste neu, statt sie neu zu sortieren." Vorher: Webseite langsam. Nachher: Webseite flüssig.
1. Pure Functions
Memoization funktioniert nur sicher bei reinen Funktionen.
add(2, 2) ist immer 4. Das kann man cachen.
getTime() ist jedes Mal anders. Das darf man nicht cachen (sonst bleibt die Uhr stehen).
Seiteneffekte (Datenbank schreiben) sind der Feind von Memoization.
2. Implementierung
Meistens nutzt man eine Hash-Map (Dictionary).
Key = Funktions-Argumente.
Value = Ergebnis.
In Python gibt es einen Decorator @lru_cache, der das mit einer Zeile Code erledigt.
1. Pointer-Immutability in React (useMemo vs Referential Equality)
Die React.js Runtime treibt Memoization an die Spitze, scheitert jedoch oft am "Equality-Gotcha".
Wenn eine Komponente <Chart data={dataChart} /> memoized gerendert ist, prüft React stupide über Object.is(oldProps.data, newProps.data).
Baut der Programmierer in einem Render-Schritt ein neues Array: const dataChart = rawData.filter(d => d.active), generiert die V8 Engine für diese RAM-Referenz einen brandneuen Heapspeicher-Pointer.
React vergleicht den Pointer (0x1A22 !== 0x1B33), bricht React.memo() ab, und das gesamte Chart zeichnet sich massiv CPU-Treibend neu ("Cascade Re-render").
Perfekte Frontend-Memoization bedarf zwingender Immutability-Striktion oder useMemo-Caps auf Setter-Arrays (Hooks), um die absolute, strikt speichereindeutige Identität der Array-Pointer-Objekte in der Garbage Collection Referenz stoisch zu konservieren (Strict Referential Equality).
2. Cache Invalidation (Zeit, Platz, LFUs und LRUs)
Ein primitiver Python dict()-Memoizer crasht Production-Server als schleichendes Memory-Leak ("Der RAM wird ewig dicker").
Professionelle Memoization in Enterprise-Architekturen erfordert Eviction-Strategien der Arrays (z. B. im Guava Cache von Java).
LRU (Least Recently Used) kickt die Ergebnisse, die am längsten nicht abgerufen wurden (beliebt für REST API Endpunkte).
LFU (Least Frequently Used) kickt die Caches, die statistisch am wenigsten populär bei der User-Verteilung ("Long Tail Requests") sind.
Extrem komplexe Algorithmen (wie TinyLFU, benutzt in Caffeine Cache) kombinieren Count-Min-Sketches, um winzigen Metadatenspeicher zu verbrauchen und fast deterministische Eviction Rate Hits von 99.8% zu erreichen, ohne den Garbage-Collection der JVM zu sprengen.
3. V8 Hidden Classes und Inline-Caching (PIC)
Der JIT-Compiler (Just In Time) in JS/Python Engines treibt heimlich hardwarenahe Memoization: Polymorphic Inline Caching (PIC).
Wenn der Interpreter den Code function get(obj) { return obj.x } das 100. Mal liest, "erinnert" sich die C++ Engine, welches Memory-Offset das Property .x in der versteckten Speicher-Struktur (Hidden Class "Shape1") hatte.
Der AST-Graph generiert Maschinen-Code (mov eax, [ebx+16]), das pure Memoization der Memory Adress-Pfade überspringt die gesamte zeitraubende Hash-Map String-Suche für O(1) Performance.
Gibt ein Programmierer exakt gleichem Code plötzlich andere Shapes (z. B. let o = {y:1, x:2} statt {x:2, y:1}), durchbricht der JIT den Cache ("Cache Miss/Deoptimization"), schmeißt den assemblierten Pfad weg und fällt gnadenlos auf 10x verlangsamten Bytecode-Parsing-Search zurück.
Quick-Check
Heißt es Memorization?
Nein! Es fehlt das "r". Es kommt von "Memo" (Notiz), nicht von "Memory" (Gedächtnis), obwohl es ähnlich funktioniert.Kostet es Speicher?
Ja. Du tauschst Rechenzeit (CPU) gegen Speicher (RAM). Wenn du Milliarden Ergebnisse cachst, stürzt das Programm ab ("Out of Memory"). Deshalb nutzt man oft Caches mit begrenzter Größe (LRU).Warum nicht alles memoizen?
Der Overhead. Das Nachschlagen in der Hash-Map kostet auch Zeit. Bei super-billigen Funktionen (a + b) ist das Nachschlagen langsamer als das Rechnen selbst.