The Codex / JavaScript / Performance Optimisation

Performance Optimisation

Making JavaScript faster — measuring before optimising, common bottlenecks, V8 engine hints, lazy loading, and memory management.

What it is, in plain English: Performance optimisation in JavaScript starts with measurement — you can't know what to fix until you know what's slow. The three main performance concerns are: runtime speed (how fast code executes), load time (how fast the page becomes interactive), and memory (avoiding leaks). The first rule: measure first, optimise second. Premature optimisation adds complexity without guaranteed benefit.

Measure first, then fix

The first rule of performance: measure before optimising. Making guesses about what's slow is almost always wrong. Use the profiler — then fix what the data says is slow.

Measuring performance

// console.time / timeEnd — easiest way to measure a block:
console.time("data processing");
const result = processData(largeArray);
console.timeEnd("data processing");
// "data processing: 234.5ms"

// performance.now() — more precise, good for comparisons:
const start = performance.now();
doSomethingExpensive();
const elapsed = performance.now() - start;
console.log(`Took ${elapsed.toFixed(2)}ms`);

// Browser DevTools — Performance tab (the real tool):
// 1. Open DevTools → Performance tab
// 2. Click Record → do the slow thing → Stop
// 3. See a flame chart: which functions took the most time
// 4. Fix the slowest ones first (biggest blocks in the chart)

Debounce and throttle — the two most impactful optimisations

// DEBOUNCE — wait until user stops doing something
// Use for: search input, form validation, resize handlers
function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

const handleSearch = debounce((query) => {
  fetch(`/api/search?q=${query}`);  // only fires 300ms after user stops typing
}, 300);

searchInput.addEventListener("input", (e) => handleSearch(e.target.value));

// THROTTLE — run at most once per interval
// Use for: scroll events, mouse moves, window resize
function throttle(fn, interval) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

const handleScroll = throttle(() => updateScrollIndicator(), 100);
window.addEventListener("scroll", handleScroll);
// Max 10 updates per second, no matter how fast the user scrolls

Avoiding common slow patterns

// ✗ Slow — querying DOM inside a loop:
for (let i = 0; i < items.length; i++) {
  document.querySelector(".list").appendChild(createItem(items[i])); // reflows each time!
}

// ✓ Fast — build once, insert once:
const fragment = document.createDocumentFragment();
items.forEach(item => fragment.appendChild(createItem(item)));
document.querySelector(".list").appendChild(fragment);  // one reflow

// ✗ Slow — reading layout properties inside a write loop (layout thrashing):
elements.forEach(el => {
  const h = el.offsetHeight;   // forces layout recalculation
  el.style.height = h + 10 + "px";  // then writes
});

// ✓ Fast — read all, then write all:
const heights = elements.map(el => el.offsetHeight);  // read phase
elements.forEach((el, i) => el.style.height = heights[i] + 10 + "px");  // write phase
Try It Yourself

Official Sources

The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.