💡

    Running Code Locally

    Performance testing requires a real browser environment. Download Node.js to run JavaScript, use Chrome DevTools Performance tab for profiling, or create a .html file to test DOM operations.

    JavaScript Performance Optimization

    Master event loop mechanics, DOM optimization, memory management, and production-grade performance patterns.

    What You'll Learn

    • Avoiding main thread blocking
    • Debouncing & throttling
    • DOM optimization patterns
    • GPU-accelerated animations
    • Memoization & data structures
    • Memory leak prevention

    The Golden Rule: Avoid Blocking the Main Thread

    JavaScript runs on a single-threaded event loop. Any task longer than 50ms is considered "slow" and causes frame drops. The key is breaking heavy work into smaller chunks.

    Avoiding Main Thread Blocking

    Break heavy work into smaller chunks to keep UI responsive

    Try it Yourself »
    JavaScript
    // Understanding the Main Thread
    // JavaScript runs on a SINGLE thread - long tasks block EVERYTHING
    
    // ❌ BAD - This blocks the UI for seconds
    function blockingTask() {
      const start = Date.now();
      // Simulate heavy computation
      let count = 0;
      for (let i = 0; i < 100000000; i++) {
        count += Math.sqrt(i);
      }
      console.log("Blocking task took:", Date.now() - start, "ms");
      return count;
    }
    
    // ✅ GOOD - Break into chunks using setTimeout
    function nonBlockingTask(callback) {
      const chunkSi
    ...

    Debouncing & Throttling Events

    Events like scroll, resize, and input can fire hundreds of times per second. Debounce waits for activity to stop; Throttle limits execution rate.

    Debouncing & Throttling

    Control event frequency for scroll, resize, and input

    Try it Yourself »
    JavaScript
    // Debouncing & Throttling - Essential for Event Performance
    
    // DEBOUNCE: Wait until user STOPS doing something
    function debounce(fn, delay) {
      let timeoutId;
      
      return function(...args) {
        // Cancel previous timer
        clearTimeout(timeoutId);
        
        // Set new timer
        timeoutId = setTimeout(() => {
          fn.apply(this, args);
        }, delay);
      };
    }
    
    // THROTTLE: Run at most once per interval
    function throttle(fn, limit) {
      let lastCall = 0;
      
      return function(...args) {
        const n
    ...

    DOM Optimization — The DOM is Slow

    DOM operations are some of the slowest parts of JavaScript. Batch updates, use DocumentFragment, and minimize layout calculations.

    DOM Optimization

    Batch updates and use DocumentFragment for faster rendering

    Try it Yourself »
    JavaScript
    // DOM Optimization - The DOM is SLOW!
    
    // ❌ BAD - Adding elements one by one (1000 layout updates)
    function slowAppend(container) {
      console.time("Slow append");
      for (let i = 0; i < 1000; i++) {
        const div = document.createElement("div");
        div.textContent = "Item " + i;
        container.appendChild(div); // Layout update each time!
      }
      console.timeEnd("Slow append");
    }
    
    // ✅ GOOD - Using DocumentFragment (1 layout update)
    function fastAppend(container) {
      console.time("Fast append");
     
    ...

    Layout Thrashing — The Silent Killer

    Alternating between reading and writing layout properties forces the browser to recalculate layout on every operation. This can make code 20-100× slower.

    Layout Thrashing

    Batch reads and writes to avoid forced layout recalculations

    Try it Yourself »
    JavaScript
    // Layout Thrashing - The Silent Performance Killer
    
    // ❌ BAD - Forces layout calculation on EVERY iteration
    function layoutThrashing(boxes) {
      console.time("Layout thrashing");
      
      for (let i = 0; i < boxes.length; i++) {
        // READ - forces layout calculation
        const width = boxes[i].offsetWidth;
        
        // WRITE - invalidates layout
        boxes[i].style.width = (width + 10) + "px";
        // Next read will force ANOTHER layout!
      }
      
      console.timeEnd("Layout thrashing");
    }
    
    // ✅ GOOD - Bat
    ...

    GPU-Accelerated Animations

    Animating transform and opacity runs on the GPU and is incredibly fast. Animating top, left, width triggers expensive layout.

    GPU-Accelerated Animations

    Use transform and opacity for smooth, hardware-accelerated animations

    Try it Yourself »
    JavaScript
    // GPU-Accelerated Animations
    
    // ❌ SLOW - Animating layout properties
    // These trigger layout + paint on EVERY frame
    const slowAnimationProperties = [
      "top", "left", "right", "bottom",
      "width", "height", "margin", "padding"
    ];
    
    // ✅ FAST - GPU-accelerated properties
    // These only trigger composite - runs on GPU!
    const fastAnimationProperties = [
      "transform",  // translateX, translateY, scale, rotate
      "opacity"     // fade in/out
    ];
    
    // Example: Smooth animation using requestAnimationFram
    ...

    Memoization — Cache Expensive Results

    If something is expensive, compute it once and cache the result. Memoization can turn exponential time complexity into linear.

    Memoization

    Cache expensive calculations to avoid redundant computation

    Try it Yourself »
    JavaScript
    // Memoization - Cache Expensive Calculations
    
    // Basic memoization function
    function memoize(fn) {
      const cache = new Map();
      
      return function(...args) {
        const key = JSON.stringify(args);
        
        if (cache.has(key)) {
          console.log("Cache hit for:", key);
          return cache.get(key);
        }
        
        console.log("Computing for:", key);
        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
      };
    }
    
    // Expensive calculation
    function fibonacci(n) {
      if 
    ...

    Efficient Data Structures

    Choosing the wrong data structure can cause massive performance loss. Use Map for key-value, Set for membership testing.

    Efficient Data Structures

    Use Map and Set for O(1) lookups and membership testing

    Try it Yourself »
    JavaScript
    // Efficient Data Structures
    
    // Object vs Map for lookups
    console.log("=== Object vs Map Performance ===");
    
    // Object lookup
    const userObject = {};
    for (let i = 0; i < 10000; i++) {
      userObject["user_" + i] = { id: i, name: "User " + i };
    }
    
    // Map lookup (FASTER for frequent operations)
    const userMap = new Map();
    for (let i = 0; i < 10000; i++) {
      userMap.set("user_" + i, { id: i, name: "User " + i });
    }
    
    console.log("Object has prototype chain overhead");
    console.log("Map is optimized for 
    ...

    Memory Management & Leak Prevention

    Memory leaks cause apps to slow down and crash. Always clean up event listeners, clear timers, and avoid capturing large data in closures.

    Memory Management

    Prevent memory leaks by cleaning up listeners and timers

    Try it Yourself »
    JavaScript
    // Memory Management & Garbage Collection
    
    // ❌ Memory Leak #1: Forgotten Event Listeners
    function leakyComponent() {
      const handler = () => console.log("Click!");
      
      // Listener added but never removed
      document.addEventListener("click", handler);
      
      // When component is destroyed, listener remains!
    }
    
    // ✅ Fixed: Clean up listeners
    function cleanComponent() {
      const handler = () => console.log("Click!");
      
      document.addEventListener("click", handler);
      
      // Return cleanup function
     
    ...

    Microtasks vs Macrotasks

    Understanding the event loop is crucial for performance. Microtasks (Promises) run before rendering; macrotasks (setTimeout) run after.

    Microtasks vs Macrotasks

    Understand how Promise callbacks differ from setTimeout

    Try it Yourself »
    JavaScript
    // Microtasks vs Macrotasks
    
    // MICROTASKS (run BEFORE next render):
    // - Promise callbacks
    // - queueMicrotask()
    // - MutationObserver
    
    // MACROTASKS (run AFTER render):
    // - setTimeout
    // - setInterval
    // - setImmediate
    // - I/O callbacks
    // - UI rendering
    
    console.log("=== Event Loop Demo ===");
    
    console.log("1. Synchronous code");
    
    setTimeout(() => {
      console.log("4. setTimeout (macrotask)");
    }, 0);
    
    Promise.resolve().then(() => {
      console.log("3. Promise.then (microtask)");
    });
    
    queueMicr
    ...

    Lazy Loading & Virtual Scrolling

    Only load what the user needs right now. Dynamic imports, lazy images, and virtual scrolling can dramatically improve perceived performance.

    Lazy Loading & Virtual Scrolling

    Load only what's needed for better perceived performance

    Try it Yourself »
    JavaScript
    // Lazy Loading & Code Splitting
    
    // 1. Dynamic Imports - Load code when needed
    async function loadHeavyModule() {
      // Module only loads when this function is called
      const module = await import("./heavy-module.js");
      return module.default;
    }
    
    // 2. Lazy Image Loading
    function lazyLoadImages() {
      const images = document.querySelectorAll("img[data-src]");
      
      const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            cons
    ...

    Performance Profiling & Measurement

    You can't optimize what you can't measure. Use the Performance API, console.time, and Chrome DevTools to find bottlenecks.

    Performance Profiling

    Measure and find bottlenecks with Performance API and DevTools

    Try it Yourself »
    JavaScript
    // Performance Profiling & Measurement
    
    // 1. Performance.now() for precise timing
    function measureExecution(fn, label) {
      const start = performance.now();
      const result = fn();
      const end = performance.now();
      console.log(label + ":", (end - start).toFixed(2) + "ms");
      return result;
    }
    
    // 2. Console timing
    function timeWithConsole() {
      console.time("operation");
      // ... do work ...
      let sum = 0;
      for (let i = 0; i < 1000000; i++) sum += i;
      console.timeEnd("operation");
      return sum;
    ...

    ⚡ Performance Mastery Summary

    • Main Thread: Keep tasks under 50ms, break heavy work into chunks
    • Debounce/Throttle: Control event frequency for scroll, resize, input
    • DOM: Batch updates, use DocumentFragment, avoid layout thrashing
    • Animations: Use transform/opacity for GPU acceleration
    • Memoization: Cache expensive calculations
    • Data Structures: Use Map/Set for O(1) operations
    • Memory: Clean up listeners, timers, and closures
    • Event Loop: Use setTimeout to yield to rendering
    • Lazy Loading: Load only what's needed, virtualize long lists
    • Profiling: Measure before optimizing with DevTools

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service