What are some tools that can be used to measure and analyze JavaScript performance?
TL;DR
Start with a reproducible user-visible problem, then choose the tool that measures that layer:
- Slow or janky interaction: Record the interaction in the browser's Performance panel and inspect long tasks, rendering work, and call stacks.
- Slow page load: Use the Network panel, Lighthouse, or WebPageTest. Compare lab results with real-user data when available.
- Growing memory use: Use heap snapshots and allocation profiles in the Memory panel.
- Slow Node.js code: Capture a CPU or heap profile with the Node.js inspector.
- One suspected hot function: Add
performance.mark()/performance.measure()instrumentation or run a carefully designed benchmark.
Measure before and after the same scenario. A microbenchmark can compare isolated snippets, but it cannot tell you whether that snippet matters to users.
Match the tool to the symptom
Chrome DevTools Performance, Network, and Memory panels
The Performance panel records browser work over time: JavaScript tasks, rendering, frames, network activity, and user interactions. It is the main tool for a page that freezes when opening a menu or typing into a large form.
- Reproduce the issue once without profiling.
- Start a recording, perform only the problematic interaction, and stop.
- Find the delayed interaction or long task and expand its call stack.
- Change the suspected code and repeat under the same CPU and network settings.
Use the Network panel instead when the delay is primarily waiting for requests. Use the Memory panel when usage grows after repeatedly opening and closing the same UI.
Lighthouse and field data
Lighthouse runs a repeatable lab audit of a page and points to likely loading and main-thread opportunities. It is useful for catching regressions in development or CI, but a single score is not production truth: lab conditions may not represent users' devices, networks, caches, or interactions.
Use field data, such as your own real-user monitoring, to confirm which problems affect real users. In particular, a navigation-only Lighthouse run cannot reproduce every interaction problem.
WebPageTest
WebPageTest records page loads in real browsers from configurable locations and network profiles. Its waterfall and filmstrip are useful for diagnosing request dependencies, caching, rendering progress, and differences between the first and repeat view. Test the same URL several times and compare medians rather than treating one run as conclusive.
User Timing API
For an application-specific operation, add marks around the work you care about:
performance.mark('filter-start');const visibleRows = filterRows(rows, query);performance.mark('filter-end');performance.measure('filter-rows', 'filter-start', 'filter-end');console.table(performance.getEntriesByName('filter-rows'));
This measures the operation inside the real application. Clear old marks and measures in long-lived pages if you generate many of them.
Node.js inspector
For a CPU-bound Node.js endpoint, capture a CPU profile under a representative workload and inspect the hottest call stacks. For increasing memory, compare heap snapshots and inspect the retaining paths. Profiling adds overhead, so be deliberate about collecting profiles in production and treat them as potentially sensitive artifacts.
Microbenchmarks
Tools such as JSBench can compare two small implementations after you have identified a real hot path. Warm up the code, consume the result so the engine cannot discard work, test representative inputs, and run enough samples. Engine optimizations and benchmark setup can otherwise make tiny differences misleading.
Further reading
- Chrome DevTools Performance panel
- Chrome DevTools Memory panel
- Lighthouse
- WebPageTest
- User Timing API
- Node.js inspector
- JSBench