READMEJavaScript

README

Module 23 Performance Optimization / .1 Performance Basics

Concept Lesson
Advanced
4 min

Learning Objective

Understand Module 23 Performance Optimization well enough to explain it, recognize it in JavaScript, and apply it in a small task.

Why It Matters

This concept is part of the foundation that later lessons and projects assume you already understand.

OptimizationPerformance MetricsJavascript Runtime PerformanceEvent Loop BlockingChunking Long Tasks
Private notes
0/8000

Notes stay private to your browser until account sync is configured.

README
1 min read18 headings

21.3 Performance Optimization

Overview

Performance optimization is crucial for delivering fast, responsive applications. This section covers JavaScript performance techniques, profiling tools, and optimization strategies.

Performance Metrics

┌────────────────────────────────────────────────────────────────────────────┐
│                     Core Web Vitals & Metrics                               │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │  LCP (Largest Contentful Paint)    ← Loading Performance            │  │
│   │  Target: < 2.5 seconds                                              │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │  FID (First Input Delay)           ← Interactivity                  │  │
│   │  Target: < 100 milliseconds                                         │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │  CLS (Cumulative Layout Shift)     ← Visual Stability               │  │
│   │  Target: < 0.1                                                      │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │  TTFB (Time to First Byte)         ← Server Response                │  │
│   │  Target: < 600 milliseconds                                         │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │  TTI (Time to Interactive)         ← Full Interactivity             │  │
│   │  Target: < 3.8 seconds                                              │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

JavaScript Runtime Performance

Event Loop & Blocking

┌────────────────────────────────────────────────────────────────────────────┐
│                        Event Loop Optimization                              │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│     Call Stack              Task Queue           Microtask Queue            │
│   ┌───────────┐          ┌───────────────┐      ┌───────────────┐          │
│   │           │          │ setTimeout    │      │ Promise.then  │          │
│   │  Heavy    │          │ setInterval   │      │ queueMicro    │          │
│   │  Sync     │────┐     │ I/O callbacks │      │ task          │          │
│   │  Task     │    │     └───────────────┘      └───────────────┘          │
│   │           │    │             │                      │                   │
│   └───────────┘    │             ▼                      ▼                   │
│                    │       ┌───────────────────────────────────────┐       │
│   ❌ BLOCKING!     └──────►│          Event Loop                   │       │
│                            │    (Can only process when stack      │       │
│   Break into chunks!       │     is empty - don't block!)         │       │
│                            └───────────────────────────────────────┘       │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Chunking Long Tasks

// ❌ Blocking - freezes UI
function processLargeArray(items) {
  for (const item of items) {
    heavyProcessing(item); // 10,000 items = blocked UI
  }
}

// ✓ Non-blocking - chunks work
async function processLargeArrayChunked(items, chunkSize = 100) {
  for (let i = 0; i < items.length; i += chunkSize) {
    const chunk = items.slice(i, i + chunkSize);
    chunk.forEach((item) => heavyProcessing(item));

    // Yield to event loop between chunks
    await new Promise((resolve) => setTimeout(resolve, 0));
  }
}

Memory Management

Memory Lifecycle

┌────────────────────────────────────────────────────────────────────────────┐
│                         Memory Lifecycle                                    │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   1. ALLOCATION          2. USAGE              3. GARBAGE COLLECTION       │
│   ┌─────────────┐       ┌─────────────┐       ┌─────────────┐              │
│   │ Primitives  │       │ Read/Write  │       │ Mark & Sweep│              │
│   │ Objects     │ ────► │ Operations  │ ────► │ Algorithm   │              │
│   │ Functions   │       │             │       │             │              │
│   └─────────────┘       └─────────────┘       └─────────────┘              │
│                                                      │                      │
│   Memory is allocated    Variables are              │                      │
│   when declaring         used in code               ▼                      │
│                                               ┌─────────────┐              │
│                                               │   FREE      │              │
│                                               │   MEMORY    │              │
│                                               └─────────────┘              │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Common Memory Leaks

┌────────────────────────────────────────────────────────────────────────────┐
│                        Common Memory Leaks                                  │
├───────────────────────────────────┬────────────────────────────────────────┤
│ Leak Type                         │ Solution                               │
├───────────────────────────────────┼────────────────────────────────────────┤
│ Forgotten event listeners         │ Remove listeners on cleanup            │
│ Closures holding references       │ Nullify references when done           │
│ Detached DOM nodes               │ Clear references to removed nodes       │
│ Timers not cleared               │ clearInterval/clearTimeout              │
│ Global variables                  │ Use block scope, avoid globals         │
│ Console.log in production        │ Remove or disable in production         │
└───────────────────────────────────┴────────────────────────────────────────┘

Caching Strategies

Memoization

// Without memoization - recalculates every time
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

// With memoization - O(n) instead of O(2^n)
function memoize(fn) {
  const cache = new Map();
  return function (...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

const fibMemoized = memoize(fibonacci);

Caching Patterns

┌────────────────────────────────────────────────────────────────────────────┐
│                         Caching Strategies                                  │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌───────────────────────────────────────────────────────────────────┐    │
│   │                     Cache Hierarchy                                │    │
│   │                                                                    │    │
│   │   L1: In-Memory (Map/WeakMap)          ← Fastest, limited size    │    │
│   │           ▼                                                        │    │
│   │   L2: Session/Local Storage            ← Persistent, per-user     │    │
│   │           ▼                                                        │    │
│   │   L3: IndexedDB                        ← Large data, structured   │    │
│   │           ▼                                                        │    │
│   │   L4: HTTP Cache / CDN                 ← Network level            │    │
│   │           ▼                                                        │    │
│   │   L5: Server-side Cache (Redis)        ← Shared, distributed      │    │
│   └───────────────────────────────────────────────────────────────────┘    │
│                                                                             │
│   Cache Invalidation Strategies:                                           │
│   • Time-based (TTL)                                                       │
│   • Version-based (cache busting)                                          │
│   • Event-based (on data change)                                           │
│   • LRU (Least Recently Used)                                              │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

DOM Performance

Batch DOM Operations

┌────────────────────────────────────────────────────────────────────────────┐
│                     DOM Operation Optimization                              │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ❌ BAD: Multiple Reflows                                                 │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │  for (item of items) {                                           │    │
│   │      container.appendChild(createEl(item));  // Reflow each time │    │
│   │  }                                                               │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                             │
│   ✓ GOOD: Batch with DocumentFragment                                     │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │  const fragment = document.createDocumentFragment();             │    │
│   │  for (item of items) {                                           │    │
│   │      fragment.appendChild(createEl(item));  // No reflow         │    │
│   │  }                                                               │    │
│   │  container.appendChild(fragment);  // Single reflow              │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                             │
│   ✓ BETTER: Virtual DOM or innerHTML (for large updates)                  │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │  container.innerHTML = items.map(createHTML).join('');           │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Layout Thrashing

// ❌ Layout thrashing - read/write cycle
function badLayout() {
  for (const el of elements) {
    const height = el.offsetHeight; // Read - forces layout
    el.style.height = height + 10 + 'px'; // Write - invalidates layout
  }
}

// ✓ Batch reads and writes
function goodLayout() {
  // Read all
  const heights = elements.map((el) => el.offsetHeight);

  // Write all
  elements.forEach((el, i) => {
    el.style.height = heights[i] + 10 + 'px';
  });
}

Lazy Loading

Lazy Loading Patterns

┌────────────────────────────────────────────────────────────────────────────┐
│                        Lazy Loading Strategies                              │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Images:                                                                   │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │  <img loading="lazy" src="image.jpg">                            │    │
│   │                                                                  │    │
│   │  // Or with Intersection Observer                               │    │
│   │  observer.observe(img);                                          │    │
│   │  // Load when visible                                            │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                             │
│   Code Splitting:                                                          │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │  // Dynamic import                                               │    │
│   │  const module = await import('./heavy-module.js');               │    │
│   │                                                                  │    │
│   │  // Route-based splitting (frameworks)                          │    │
│   │  const Dashboard = lazy(() => import('./Dashboard'));            │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                             │
│   Data:                                                                    │
│   ┌──────────────────────────────────────────────────────────────────┐    │
│   │  // Infinite scroll / pagination                                 │    │
│   │  // Load more data as user scrolls                              │    │
│   │  // Virtual lists for large datasets                            │    │
│   └──────────────────────────────────────────────────────────────────┘    │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Debouncing & Throttling

┌────────────────────────────────────────────────────────────────────────────┐
│                    Debounce vs Throttle                                     │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   DEBOUNCE: Wait until activity stops                                      │
│   ─────────────────────────────────────                                    │
│                                                                             │
│   Events:    ×  × ×  ×    ×  × ×  ×                 │                      │
│   Time:      ──────────────────────────────────────►                       │
│   Executes:                                         ◆                      │
│                                                     ↑                      │
│                                           Only after pause                  │
│                                                                             │
│   Use for: Search input, window resize, form validation                    │
│                                                                             │
│   ─────────────────────────────────────────────────────────────────────    │
│                                                                             │
│   THROTTLE: Execute at most once per interval                              │
│   ───────────────────────────────────────────                              │
│                                                                             │
│   Events:    ×  × ×  ×    ×  × ×  ×                                        │
│   Time:      ──────────────────────────────────────►                       │
│   Executes:  ◆        ◆        ◆        ◆                                  │
│              ↑        ↑        ↑        ↑                                  │
│              Fixed intervals                                                │
│                                                                             │
│   Use for: Scroll events, mouse move, API rate limiting                    │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Web Workers

Offloading Heavy Computation

┌────────────────────────────────────────────────────────────────────────────┐
│                         Web Workers                                         │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Main Thread                         Worker Thread                         │
│   ┌─────────────────────┐            ┌─────────────────────┐               │
│   │                     │  postMsg   │                     │               │
│   │   UI Rendering      │ ─────────► │  Heavy Computation  │               │
│   │   Event Handling    │            │  Data Processing    │               │
│   │   DOM Access        │ ◄───────── │  Complex Algorithms │               │
│   │                     │  postMsg   │                     │               │
│   └─────────────────────┘            └─────────────────────┘               │
│           │                                   │                             │
│           │   ✓ UI stays responsive          │   ✓ True parallelism       │
│           │   ✓ No blocking                  │   ✗ No DOM access           │
│           │                                  │   ✗ Limited APIs            │
│                                                                             │
│   // Main thread                                                           │
│   const worker = new Worker('worker.js');                                  │
│   worker.postMessage({ data: largeArray });                                │
│   worker.onmessage = (e) => console.log(e.data.result);                   │
│                                                                             │
│   // worker.js                                                             │
│   onmessage = (e) => {                                                     │
│       const result = heavyProcessing(e.data);                              │
│       postMessage({ result });                                             │
│   };                                                                       │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Network Optimization

Request Optimization

┌────────────────────────────────────────────────────────────────────────────┐
│                      Network Optimization                                   │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Reduce Requests:                                                         │
│   • Bundle JavaScript/CSS files                                            │
│   • Use CSS sprites or icon fonts                                          │
│   • Inline critical resources                                              │
│                                                                             │
│   Reduce Size:                                                             │
│   • Enable gzip/brotli compression                                         │
│   • Minify JavaScript/CSS/HTML                                             │
│   • Optimize images (WebP, AVIF)                                           │
│   • Remove unused code (tree shaking)                                      │
│                                                                             │
│   Caching:                                                                 │
│   • Set proper Cache-Control headers                                       │
│   • Use ETags for validation                                               │
│   • Implement Service Workers                                              │
│                                                                             │
│   Loading Strategy:                                                        │
│   ┌────────────────────────────────────────────────────────────────────┐  │
│   │  <link rel="preload" href="critical.js" as="script">              │  │
│   │  <link rel="prefetch" href="next-page.js">                        │  │
│   │  <link rel="preconnect" href="https://api.example.com">          │  │
│   │  <script defer src="app.js"></script>                             │  │
│   │  <script async src="analytics.js"></script>                       │  │
│   └────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Profiling Tools

Browser DevTools

┌────────────────────────────────────────────────────────────────────────────┐
│                     Performance Profiling Tools                             │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Chrome DevTools:                                                         │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │ Performance Panel    → Record runtime performance                   │ │
│   │ Memory Panel        → Heap snapshots, allocation timeline          │ │
│   │ Network Panel       → Request waterfall, timing                    │ │
│   │ Lighthouse          → Automated performance audit                  │ │
│   │ Coverage            → Find unused CSS/JS                           │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│   JavaScript APIs:                                                         │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │ performance.now()         → High-resolution timestamps             │ │
│   │ performance.mark()        → Custom markers                         │ │
│   │ performance.measure()     → Measure between marks                  │ │
│   │ PerformanceObserver       → Observe performance entries            │ │
│   │ console.time/timeEnd()    → Simple timing                          │ │
│   │ console.profile()         → CPU profiling                          │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Performance Optimization Checklist

┌────────────────────────────────────────────────────────────────────────────┐
│                   Performance Optimization Checklist                        │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│ JavaScript:                                                                │
│ □ Minimize bundle size (code splitting, tree shaking)                      │
│ □ Avoid synchronous operations (use async/await)                           │
│ □ Debounce/throttle event handlers                                         │
│ □ Use Web Workers for heavy computation                                    │
│ □ Implement proper error handling                                          │
│                                                                             │
│ Memory:                                                                    │
│ □ Remove event listeners on cleanup                                        │
│ □ Clear timers and intervals                                               │
│ □ Avoid creating unnecessary objects                                       │
│ □ Use WeakMap/WeakSet for cache                                           │
│ □ Profile for memory leaks                                                 │
│                                                                             │
│ DOM:                                                                       │
│ □ Batch DOM reads and writes                                               │
│ □ Use DocumentFragment for multiple inserts                                │
│ □ Leverage event delegation                                                │
│ □ Virtual scrolling for long lists                                         │
│                                                                             │
│ Network:                                                                   │
│ □ Enable compression (gzip/brotli)                                         │
│ □ Implement caching strategy                                               │
│ □ Lazy load non-critical resources                                         │
│ □ Preload critical resources                                               │
│                                                                             │
│ Rendering:                                                                 │
│ □ Optimize critical rendering path                                         │
│ □ Minimize reflows and repaints                                            │
│ □ Use CSS containment                                                      │
│ □ Prefer CSS animations over JS                                            │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘

Key Takeaways

  1. Measure first - Use profiling tools to identify bottlenecks
  2. Don't block the main thread - Chunk work, use Web Workers
  3. Minimize DOM access - Batch operations, use virtual lists
  4. Cache wisely - Memoize expensive computations
  5. Lazy load - Load only what's needed
  6. Optimize network - Compress, cache, preload
  7. Monitor in production - Use Real User Monitoring (RUM)

Files in This Section

  • README.md - This documentation
  • examples.js - Performance optimization examples
  • exercises.js - Performance improvement exercises

Skill Check

Test this lesson

Answer 4 quick questions to lock in the lesson and feed your adaptive practice queue.

--
Score
0/4
Answered
Not attempted
Status
1

Which module does this lesson belong to?

2

Which section is covered in this lesson content?

3

Which term is most central to this lesson?

4

What is the best way to use this lesson for real learning?

Your answers save locally first, then sync when account storage is available.
Practice queue