diff --git a/07_js-debug/faq/reference-error.ts b/07_js-debug/faq/reference-error.ts new file mode 100644 index 0000000..5a24250 --- /dev/null +++ b/07_js-debug/faq/reference-error.ts @@ -0,0 +1,30 @@ +{ + const firstName = 'John'; + + // if (firstName === John) { + // // ReferenceError: John is not defined + // console.log(firstName); + // } + + // if (firstname === 'John') { + // // Uncaught ReferenceError: firstname is not defined + // console.log(firstName); + // } + + if (firstName === 'John') { + console.log(firstName); + } + + function greet() { + console.log('Hello, ' + fullName); // Cannot find name 'fullName'. + console.log(typeof fullName); + } + + // greet(); // => ReferenceError: fullName is not defined + + // function greet(fullName) { + // console.log(`Hello, ${fullName}`); + // } + + greet('John Wick'); +} diff --git a/07_js-debug/unterricht/tag41/01_inversion/01_verschachtelte-ifs.html b/07_js-debug/unterricht/tag41/01_inversion/01_verschachtelte-ifs.html new file mode 100644 index 0000000..780ee0b --- /dev/null +++ b/07_js-debug/unterricht/tag41/01_inversion/01_verschachtelte-ifs.html @@ -0,0 +1,65 @@ + + + + + + Nesting if-statements + + + +
+
+

Nesting if-statements

+
+
+ + + diff --git a/07_js-debug/unterricht/tag41/01_inversion/02_optimierung-durch-inversion.html b/07_js-debug/unterricht/tag41/01_inversion/02_optimierung-durch-inversion.html new file mode 100644 index 0000000..2d113e1 --- /dev/null +++ b/07_js-debug/unterricht/tag41/01_inversion/02_optimierung-durch-inversion.html @@ -0,0 +1,68 @@ + + + + + + Nesting if-statements vermeiden über inversion + + + +
+
+

Nesting if-statements vermeiden über inversion

+
+
+ + + diff --git a/07_js-debug/unterricht/tag41/01_inversion/03_performance-test-inversion.js b/07_js-debug/unterricht/tag41/01_inversion/03_performance-test-inversion.js new file mode 100644 index 0000000..1e63f5f --- /dev/null +++ b/07_js-debug/unterricht/tag41/01_inversion/03_performance-test-inversion.js @@ -0,0 +1,57 @@ +'use strict'; + +const isSystemUpgrading = false; +const isLoggedIn = true; +const hasAdminRights = true; + +const items = [ + { name: 'Item A', cost: 150 }, + { name: 'Item B', cost: 250 }, + { name: 'Item C', cost: 350 }, +]; + +function runNested() { + let counter = 0; + if (!isSystemUpgrading) { + if (isLoggedIn) { + if (hasAdminRights) { + for (let i = 0; i < items.length; i++) { + if (items[i].cost > 200) counter++; + } + } + } + } + return counter; +} + +function runGuard() { + let counter = 0; + if (isSystemUpgrading) return counter; + if (!isLoggedIn) return counter; + if (!hasAdminRights) return counter; + + for (let i = 0; i < items.length; i++) { + if (items[i].cost > 200) counter++; + } + return counter; +} + +const ITERATIONS = 10_000_000; + +// Warmup +for (let i = 0; i < 100_000; i++) { + runNested(); + runGuard(); +} + +console.time('Verschachtelt'); +for (let i = 0; i < ITERATIONS; i++) runNested(); +console.timeEnd('Verschachtelt'); + +console.time('Early Returns'); +for (let i = 0; i < ITERATIONS; i++) runGuard(); +console.timeEnd('Early Returns'); + +// In diesem Test laufen beide Varianten im Chrome V8-Engine praktisch gleich schnell (innerhalb normaler CPU-Schwankungen). + +// Fazit: Verwende Early Returns (Guard Clauses). Sie bieten zwar keinen nennenswerten Performance-Vorsprung gegenüber verschachtelten Abfragen, reduzieren aber die zyklomatische Komplexität und machen den Code deutlich lesbarer. diff --git a/07_js-debug/unterricht/tag41/01_inversion/04_README.md b/07_js-debug/unterricht/tag41/01_inversion/04_README.md new file mode 100644 index 0000000..943bd0c --- /dev/null +++ b/07_js-debug/unterricht/tag41/01_inversion/04_README.md @@ -0,0 +1,38 @@ +## Kein Performanceunterschied bei Inversion + +### 1. AST-Normalisierung & SSA (Control Flow Graphs) + +V8 (über den Turbofan-Optimierungs-Compiler) führt deinen Code nicht zeilenweise so aus, wie du ihn schreibst: + +* **Control Flow Graph (CFG):** V8 wandelt sowohl verschachtelte Blöcke als auch Early Returns in dieselbe abstrakte Repräsentation um (Static Single Assignment / SSA Form). +* **Pfad-Reduktion:** Ein verschachtelter Baum `if (A) { if (B) { if (C) { ... } } }` wird im Zwischencode auf denselben Entscheidungspfad reduziert wie `if (!A) return; if (!B) return; if (!C) return;`. +* **Identischer Maschinencode:** Sobald Turbofan den Code optimiert, erzeugen beide Varianten exakt dieselbe Sequenz aus bedingten Sprungbefehlen (`test`, `jnz` / `jz`) auf Assemblerebene. + +--- + +### 2. Hardware-Ebene: CPU Branch Prediction + +Unabhängig von der JS-Engine entscheidet die Hardware über die Geschwindigkeit von Verzweigungen: + +* Wenn Bedingungen wie `isLoggedIn` stabil sind (z. B. immer `true`), lernt der **Branch Predictor** der CPU das Muster nach wenigen Durchläufen. +* Die CPU führt den Zweig spekulativ ohne Pipeline-Stall aus (Branch Prediction Penalty = 0 Takte). +* Ob der nicht genommene Zweig am Ende der Funktion (`nested`) oder direkt hinter dem Check (`early return`) liegt, macht für die Ausführungszeit der CPU keinen Unterschied. + +--- + +### 3. Warum misst man im Firefox (SpiderMonkey) manchmal Unterschiede? + +SpiderMonkey (Firefox) und V8 (Chrome) verfolgen unterschiedliche Strategien bei der Bytecode-Erzeugung und den JIT-Stufen: + +| Aspekt | Chrome (V8) | Firefox (SpiderMonkey) | +| --- | --- | --- | +| **Pipeline** | Ignition (Interpreter) $\rightarrow$ Sparkplug $\rightarrow$ Maglev $\rightarrow$ Turbofan | C++ Interpreter $\rightarrow$ Baseline Interpreter $\rightarrow$ Baseline Compiler $\rightarrow$ WarpMonkey | +| **Bytecode-Layout** | V8 optimiert Jump-Targets früh im Bytecode-Generator; Basic Blocks werden linear angeordnet. | SpiderMonkey behält in frühen Phasen oft ein Bytecode-Layout bei, das näher an der Quellcode-Struktur liegt. | +| **Bailout / OSR** | Sehr aggressives Inlining und Dead-Code-Elimination im `Maglev`/`Turbofan`-Layer. | `WarpMonkey` nutzt Transpilation über CacheIR; je nach Verschachtelungstiefe können Scope- und Frame-Handling im Baseline-Tier minimal variieren. | + +In **nicht-hochoptimiertem Code** (z. B. Skripte, die nur wenige Male laufen und im Interpreter bzw. Baseline JIT verbleiben): + +* Verursacht tiefe Verschachtelung in manchen Engines zusätzlichen Overhead beim Verwalten von Lexical Environments/Scopes auf dem Stack. +* Early Returns erlauben es dem Interpreter, den aktuellen Stack-Frame schneller abzubauen, ohne tiefer liegende Scope-Hierarchien zu durchlaufen. + +Sobald der Code jedoch "heiß" läuft (nach einigen tausend Iterationen), eliminieren sowohl Turbofan als auch WarpMonkey diesen Unterschied vollständig. \ No newline at end of file diff --git a/07_js-debug/unterricht/tag41/01_inversion/04_README.pdf b/07_js-debug/unterricht/tag41/01_inversion/04_README.pdf new file mode 100644 index 0000000..23e0860 Binary files /dev/null and b/07_js-debug/unterricht/tag41/01_inversion/04_README.pdf differ diff --git a/07_js-debug/unterricht/tag41/02_extraction/01_verschachtelte-ifs.html b/07_js-debug/unterricht/tag41/02_extraction/01_verschachtelte-ifs.html new file mode 100644 index 0000000..2ad1d7d --- /dev/null +++ b/07_js-debug/unterricht/tag41/02_extraction/01_verschachtelte-ifs.html @@ -0,0 +1,61 @@ + + + + + + Nested if-statements + + + +
+
+

Nested if-statements

+
+
+ + + diff --git a/07_js-debug/unterricht/tag41/02_extraction/02_optimierung-durch-extraction.html b/07_js-debug/unterricht/tag41/02_extraction/02_optimierung-durch-extraction.html new file mode 100644 index 0000000..4852987 --- /dev/null +++ b/07_js-debug/unterricht/tag41/02_extraction/02_optimierung-durch-extraction.html @@ -0,0 +1,79 @@ + + + + + + Extraction + + + +
+
+

Extraction

+
+
+ + + diff --git a/07_js-debug/unterricht/tag41/03_dry/01_calc-rectangle.html b/07_js-debug/unterricht/tag41/03_dry/01_calc-rectangle.html new file mode 100644 index 0000000..c6c6879 --- /dev/null +++ b/07_js-debug/unterricht/tag41/03_dry/01_calc-rectangle.html @@ -0,0 +1,41 @@ + + + + + + DRY - Don't Repeat Yourself + + + +
+
+

DRY - Don't Repeat Yourself

+
+
+ + + diff --git a/07_js-debug/unterricht/tag41/03_dry/02_optimierung-durch-dry.html b/07_js-debug/unterricht/tag41/03_dry/02_optimierung-durch-dry.html new file mode 100644 index 0000000..5508bfc --- /dev/null +++ b/07_js-debug/unterricht/tag41/03_dry/02_optimierung-durch-dry.html @@ -0,0 +1,96 @@ + + + + + + DRY - Don't Repeat Yourself - Regel anwenden + + + +
+
+

DRY - Don't Repeat Yourself - Regel anwenden

+
+
+
+ + + + + diff --git a/07_js-debug/unterricht/tag41/04_error-types/01_syntax-error.html b/07_js-debug/unterricht/tag41/04_error-types/01_syntax-error.html new file mode 100644 index 0000000..26c4e24 --- /dev/null +++ b/07_js-debug/unterricht/tag41/04_error-types/01_syntax-error.html @@ -0,0 +1,63 @@ + + + + + + Syntax Error + + + +
+
+

Syntax Error

+
+
+ + + diff --git a/07_js-debug/unterricht/tag41/04_error-types/02_reference-error.html b/07_js-debug/unterricht/tag41/04_error-types/02_reference-error.html new file mode 100644 index 0000000..55899a1 --- /dev/null +++ b/07_js-debug/unterricht/tag41/04_error-types/02_reference-error.html @@ -0,0 +1,50 @@ + + + + + + Reference Error + + + +
+
+

Reference Error

+
+
+ + +