What you'll learn
Performance work begins with user-centered measurement. Improve algorithms and payloads first, remove main-thread contention, and use workers only when profiling shows CPU-bound work.
By the end of this lesson, you'll be able to:
- Profile CPU, memory, loading, and rendering
- Find common JavaScript memory leaks
- Move suitable work to workers
Core mental model
Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.
| Concept | What it means | Decision rule |
|---|---|---|
| Budget | Numeric limit tied to user experience | Set before optimization and enforce in CI |
| Heap retention | Reachable references keep memory alive | Inspect retaining paths, not just allocation counts |
| Worker | Separate thread communicating by messages | Use for substantial CPU work with transferable data |
Professional workflow
Build the behavior in small, observable steps. Each step should leave something you can inspect or test.
- Describe the performance budget boundary: inputs, outputs, state, timing, and expected failures.
- Implement the smallest correct path with names that expose intent.
- Add edge cases and failure handling before introducing abstractions.
- Verify behavior with realistic data and one deliberately adversarial example.
- Refactor only after the observable behavior is protected.
Make behavior observable
Guided code lab
Measure one operation
Performance marks produce a named duration that can be compared after changes.
performance.mark("report-start");
const report = buildReport(records);
performance.mark("report-end");
performance.measure("build-report", "report-start", "report-end");
console.log(performance.getEntriesByName("build-report")[0].duration);Move CPU work to a worker
The main thread sends serializable data and receives a result without blocking interaction.
// main.js
const worker = new Worker(new URL("./worker.js", import.meta.url), { type: "module" });
worker.postMessage(records);
worker.addEventListener("message", event => renderReport(event.data));
// worker.js
self.addEventListener("message", event => {
self.postMessage(buildReport(event.data));
});Production practice
Contract
Write down the performance budget quality target, ownership boundary, evidence, and acceptable tradeoffs.
Verification
Use repeatable automated checks plus a realistic end-to-end scenario; include failure and recovery behavior.
Operations
Track a small set of user-centered signals and revisit the decision when evidence changes.
Common failure mode
Independent workshop
Profile and optimize a large progress dashboard.
Your finished workshop must include:
- A before/after performance trace
- One verified leak fix
- A worker or documented reason not to use one
Definition of done
Recap & quick check
Key takeaways
- Measure user-centered outcomes
- Algorithm choice dominates syntax tweaks
- Reachability explains leaks
- Workers trade messaging cost for parallel CPU work
Quick check
1. What should happen before optimization?
2. What keeps an unused object alive?
3. What is worker communication based on?
Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.