How to measure JS code performance?
Quick measurements (instrumenting the code)
Browser
javascript
// A precise timer (in ms, with fractions)
const t0 = performance.now();
// ... code ...
const t1 = performance.now();
console.log(`Time: ${(t1 - t0).toFixed(2)} ms`);javascript
// User Timing API: marks and measures
performance.mark('A');
// ... code ...
performance.mark('B');
performance.measure('my-op', 'A', 'B');
console.table(performance.getEntriesByName('my-op'));javascript
// Quick and simple
console.time('op');
// ... code ...
console.timeEnd('op');Node.js
javascript
// perf_hooks - monotonic timers
const { performance, PerformanceObserver } = require('node:perf_hooks');
performance.mark('A');
// ... code ...
performance.mark('B');
performance.measure('op', 'A', 'B');
new PerformanceObserver(list => console.table(list.getEntries()))
.observe({ entryTypes: ['measure'] });Profiling (to understand "where" it lags)
Browser DevTools
- Performance (or Performance Insights): record → get a flame chart (hot functions), FPS, layout/recalc style, long tasks (≥50 ms).
- Memory: Heap snapshot / Allocation instrumentation - looking for leaks and "garbage".
- Coverage: how much JS/CSS is actually executed (affects TBT).
Node.js
node --inspectand Chrome DevTools → CPU profile, heap.node --prof+prof-processor clinic.js / 0x for convenient flame graphs.
Microbenchmarks (comparing implementations)
- Benchmark.js / tinybench - do JIT warm-up, many iterations, statistics.
javascript
import Benchmark from 'benchmark';
const suite = new Benchmark.Suite();
function a(arr){ /* variant A */ }
function b(arr){ /* variant B */ }
suite
.add('A', () => a(data))
.add('B', () => b(data))
.on('cycle', e => console.log(String(e.target)))
.on('complete', function () {
console.log('Faster:', this.filter('fastest').map('name'));
})
.run({ async: true });Important: warm up the test (discard first run), fix the input data, run several passes, disable unnecessary tabs/extensions.
Measuring UI "liveliness"
- Long Tasks API: catch main-thread blocking.
javascript
new PerformanceObserver((list) => {
for (const e of list.getEntries()) {
console.log('Long task', e.duration.toFixed(1), 'ms');
}
}).observe({ entryTypes: ['longtask'] });- rAF/FPS: a simple smoothness indicator.
javascript
let last = performance.now(), frames = 0;
function tick(ts){
frames++;
if (ts - last >= 1000) { console.log('FPS:', frames); frames = 0; last = ts; }
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);Network and render metrics (page-level)
- Navigation/Resource Timing (
performance.getEntriesByType('navigation'|'resource')) - TTFB, resource loading. - Core Web Vitals (LCP, CLS, INP/TBT) - deploy web-vitals on real traffic.
- Lighthouse (one-off) - catches regressions, but doesn't replace field metrics.
Methodology: how to measure correctly
- State the goal (CPU-bound part? GC? Layout? Network?).
- Isolate the context: disable the network/DOM if you're measuring a pure algorithm.
- Warm up the JIT: do a few "throwaway" runs.
- Repetitions and statistics: the median/quantiles matter more than the average.
- Control the noise: fix the data, the input size, limit background processes.
- Look at the flame (flame chart), not just the numbers - optimize the "hot" bottlenecks.
- Check for regressions in CI (for example, a small bench + thresholds).
What to measure in typical scenarios
- Algorithms/collections → microbench (Benchmark.js) +
performance.now. - UI interactivity → DevTools Performance + Long Tasks + FPS.
- Rendering/styles → the Rendering/Layout/Styles tabs in the profiler, avoid layout thrashing.
- Memory/leaks → Heap snapshots, Allocation timeline.
- Node APIs →
perf_hooks, CPU profile, checking for sync methods (replace with async/worker_threads).
Anti-patterns
- A single "by eye" run - noise and the JIT will distort the picture.
- Microbenchmarking DOM operations: results depend on the real tree/styles. Profile in DevTools instead.
- Comparing without identical input data.
- Optimizing without a flamechart - easy to "fix the wrong spot".
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.