Using Chrome DevTools for JS Performance Tuning

Find and fix slow JavaScript with Chrome DevTools. Learn to record performance profiles, read flame charts, use CPU throttling, and identify bottlenecks that make your app feel sluggish.

8 min read

Chrome DevTools has a full performance analysis suite built into every Chrome browser. You can record exactly what your JavaScript does during a user interaction, see a visual timeline of every function call, and find the specific lines that take the most time. This guide covers the Performance panel, CPU throttling, the flame chart, and the Sources debugger for performance work.

Recording a performance profile

Open DevTools (F12 or right-click anywhere and choose Inspect) and click the Performance tab. The workflow is:

  • Click the circle record button (or press Ctrl+E).
  • Perform the action you want to analyze: click a button, scroll, type in a field.
  • Click Stop (or press Ctrl+E again).

You now have a profile showing everything that happened: JavaScript execution, layout recalculations, style updates, painting, and rendering.

DevTools performance profiling workflow

Record for 3 to 5 seconds. Longer recordings generate too much data to analyze easily. Focus on one interaction at a time.

Reading the flame chart

The flame chart is the main visualization in the Performance panel. Each horizontal bar represents a function call, and reading it comes down to three rules.

Width equals time, so a wide bar means the function took a long time to complete. Stacking shows the call hierarchy: if function A calls function B, B's bar sits on top of A's bar, and the full height shows the call stack depth. Tall stacks with wide bars are the best targets, since a stack that is both deep and wide is where the most time is being spent.

The x-axis is time. The y-axis is the call stack. Bars are color-coded:

ColorMeaning
YellowJavaScript execution
PurpleStyle recalculation and layout
GreenPaint and compositing
GrayBrowser internal work

If most of the flame chart is yellow, JavaScript is the bottleneck. If it is purple, you are triggering too many layout recalculations.

Click any bar to jump to the Sources panel showing the exact function code. The Bottom-Up tab below the flame chart lists every function sorted by total time. This is often the fastest way to find the expensive function.

CPU throttling

Your development machine is probably faster than what most users have. Chrome can simulate a slower CPU to reveal problems that are invisible at full speed:

  • In the Performance panel, find the CPU dropdown next to the record button.
  • Select 4x slowdown or 6x slowdown.
  • Record your interaction again and compare.

A function that takes 5ms on a fast machine takes 30ms at 6x slowdown. If the throttled profile shows frames taking longer than 16ms (the budget for 60fps), your users on mid-range devices are experiencing jank.

The Sources panel for line-by-line analysis

When you have identified a slow function in the flame chart, open the Sources panel. The debugger runs inside this panel:

  • Breakpoints: Click a line number to set a breakpoint. The next time that line executes, the debugger pauses and you can inspect variables, the call stack, and step through line by line.
  • Conditional breakpoints: Right-click a line number and choose "Add conditional breakpoint." Enter a condition like i > 100 to pause only on the 101st iteration of a loop.
  • Logpoints: Right-click and choose "Add logpoint." Instead of pausing, it logs a message to the console. This is useful for tracking values in hot loops without stopping.
javascriptjavascript
function findSlowRendering(items) {
  // Set a breakpoint on this line to inspect `items.length`
  for (let i = 0; i < items.length; i++) {
    // Add a logpoint here: "Processing item", i, items[i].name
    renderItem(items[i]);
  }
}

Finding the real bottleneck

Here is a systematic approach to finding what to optimize:

  • Identify slow frames. In the Performance panel, look at the FPS chart at the top. Drops below 60fps indicate jank, so click those regions to zoom in.
  • Switch to the Bottom-Up tab. This sorts every function by total self time. The function at the top is your primary suspect, and it may not be the function you expect.
  • Check the Call Tree tab. This shows the inclusive time, meaning the function plus everything it calls. A high inclusive time with a low self time means the real work is happening in its children.
  • Verify with performance.now(). Before optimizing, wrap the suspect code in timing calls so you can measure the exact before-and-after improvement:
javascriptjavascript
const start = performance.now();
suspectFunction();
const end = performance.now();
console.log(`Before fix: ${end - start}ms`);

Common performance problems and what they look like

Forced synchronous layouts. You read a layout property (like offsetHeight) right after changing the DOM, forcing the browser to recalculate layout before the next frame. In the flame chart, you see alternating purple (layout) and yellow (JS) bars in a tight pattern inside one frame.

Expensive event handlers. A scroll or mousemove handler that does heavy work on every event. The flame chart shows the same yellow bar firing at 60+ times per second. Fix with debouncing or throttling.

Long garbage collection pauses. The flame chart shows sawtooth patterns: memory climbs, then a wide gray bar appears while the garbage collector runs. Fix by reducing object allocation inside hot loops.

Large recalculate style blocks. Wide purple bars after JavaScript runs. This means your code changed classes or inline styles on many elements at once. Batch DOM reads and writes separately, or use requestAnimationFrame.

Taking a heap snapshot for memory

The Memory panel (separate tab in DevTools) captures JavaScript heap snapshots. This is useful when performance profiling shows garbage collection pauses:

  • Click the Memory tab.
  • Select Heap snapshot and click Take snapshot.
  • Perform the action you are investigating.
  • Take a second snapshot.
  • Use the Comparison view to see what objects were allocated between snapshots.

Look for large object counts, detached DOM elements (nodes removed from the page but still held in JS variables), and unexpected retained arrays.

For more on measuring execution time programmatically, see how to measure JavaScript execution time accurately. For debugging the errors that show up during profiling, see the try...catch guide.

Rune AI

Rune AI

Key Insights

  • Use the Performance panel to record a few seconds of interaction and see a flame chart of all function calls.
  • Wider bars in the flame chart mean longer execution time; start optimization there.
  • Enable CPU throttling (4x or 6x slowdown) to simulate performance on low-end devices.
  • The Bottom-Up and Call Tree tabs sort functions by total time, making bottlenecks obvious.
  • Set breakpoints in the Sources panel to pause execution and inspect variables at specific points.
  • Always measure before and after optimizing to confirm the fix actually helped.
RunePowered by Rune AI

Frequently Asked Questions

How do I open the Performance panel in Chrome DevTools?

Open DevTools (F12 or Ctrl+Shift+I), then click the Performance tab. Alternatively, from the Chrome menu go to More Tools > Developer Tools, then select Performance.

What is a flame chart and how do I read it?

A flame chart shows the call stack over time, with each function call as a horizontal bar. Wider bars mean longer execution. Bars stacked on top show the call hierarchy: the top bar called the ones below it. Tall stacks with wide bars are your optimization targets.

What does CPU throttling do and why should I use it?

CPU throttling artificially slows down the processor to simulate a slower device. It reveals performance issues that are invisible on a fast development machine but affect real users on mid-range phones or laptops.

Conclusion

Chrome DevTools turns guesswork into data. The Performance panel shows you exactly which functions take the most time, the Sources debugger lets you step through hot paths line by line, and CPU throttling reveals how your code behaves on slower devices. The workflow is simple: record, read the flame chart, find the widest bars, and optimize what matters most.