At the inaugural WebPerfDays, Loreena Lee of the Gmail Client Performance Team gave a great talk on using the new Profiles feature of Chrome Developer Tools to make Gmail faster. In their hunt to find performance issues within the Gmail client interface, her team ran into the limitations of their current toolset. By collaborating with the Chrome team, the profile tool made quite a few improvements. Lee pointed out a few misconceptions about memory and performance. In this age of abundant memory, there is a belief that more memory automatically improves the performance of an application. The Gmail team found that this does not hold true in all cases. By collecting data from the thousands of Google employees using Gmail themselves, Lee and her team found that as the memory footprint grew, so did the client-side latency. They also discovered that as the process size got bigger, the garbage collector struggled to function. Memory leaks were found to be the biggest drain on client-side performance. So what’s the biggest culprit in memory leaks in Gmail? Event listeners, or more specifically listen() without unlisten() to an event from Google’s Closure Library events.js. The team also found many missing dispose() for events that created listeners from disposable.js. The greater message for both of these issues is that the garbage collector does not always clean up properly in all cases. In fact, there were instances where up to 25% of the garbage was not collected. So for long-running apps, like Gmail, it is imperative to use tools like the profiler to identify these issues which will only show themselves over time.

Finding Memory Bloat

To demonstrate how to use the Developer Tools to find memory problems, I chose a heavy JavaScript heavy application that I happen to have open in one of my tabs. (We use it at New Relic for project management.) I opened the Timeline view in the Developer Tools and recorded the memory usage for 10 minutes. Below is a graph of that usage. On the left is the “launch” of the application -- the first 5 minutes are my interactions with the application and the second 5 minutes are the app sitting idle in the tab.

You can see the memory usage grow as I used the application for the first 5 minutes, and you’ll also see some normal garbage collection happening as I move to different portions of the application. To see if there were any memory leaks, I let the application idle for 5 more minutes. The memory footprint grew during the second half of the test, but garbage collected itself. What didn’t happen, and what shows some memory issues, is that the total footprint never fell below the lowest points around the 5 minute mark. Memory allocations made during the app usage in the first 5 minutes were never garbage collected even though I had moved to an entirely different portion of the site.

Identifying the Culprit

Now that there appears to be a memory issue somewhere, we have to hunt down where it is coming from. This is where we can take advantage of the Profiles by taking snapshots of the head before and after the suspected bloat. I took a snapshot of the application after it had fully loaded but before taking any actions, I took a second snapshot after I had walked through the same steps from the timeline view above (the footprint had grown by 60%). Using the comparison view, I can see there were 1,587 <div> elements created and only 34 deleted. Drilling down, I can see that the vast majority of the elements are detached from the DOM.

DOM leaks commonly occur when an element is appended to a DOM, additional elements are appended to the first and then the original is removed from the DOM without removing the secondary elements. You can see an example over at Google’s Developer Tools documentation. Once you have identified the leak, you can dive into the profile to see the function calls creating the object so that you can add the necessary code to clean them up after they are no longer needed. Amongst others, infinite scrolling features are often guilty of this kind of leak. For information on the Profile Panel, get the full introduction straight from Google. And if you haven’t used the panel recently, give it another look. The hard work of the Gmail Client Performance and Chrome teams have really made an invaluable feature for any developer building long-running JavaScript applications.