Skip to content

Memory leaks

Nick Partridge edited this page Jun 14, 2021 · 2 revisions

After investigating some memory leaks the following are some helpfull tips on how best to find memory leaks.

To link or not to link

Linking @elastic/charts to kibana can surface memory leaks that may not be present in our storybook so keep this in mind when investigating leaks and deciding when to link via yarn link:kibana.

Use incognito 🥸 browser

The incognito browser disables most if not all extensions that they themselves could have memory leaks and create misleading noise in the memory heap snapshot.

Comment out redux dev tools

The redux dev tools extension can create noice when looking at the heap snapshot so it's best to remove this during your investigation. See packages/charts/src/components/chart.tsx for code below.

const getMiddlware = (id: string): StoreEnhancer => {
  const middlware: Middleware<any, any, any>[] = [];

  // if (typeof window !== 'undefined' && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) {
  //   // eslint-disable-next-line @typescript-eslint/no-unsafe-call
  //   return (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
  //     trace: true,
  //     name: `@elastic/charts (id: ${id})`,
  //   })(applyMiddleware(...middlware));
  // }

  return applyMiddleware(...middlware);
};

Preliminary discovery with performance monitor

Before generating a detailed heap snapshot, memory leaks can be identified using Chrome's performance monitor tool. One red flag with respect to DOM elements is an ever-increasing node count where even with garbage collection the DOM node count continues to grow for a given action.

performance monitor

Notice the green series representing node count, always increases. A normal chart would look like a sawtooth shape with increases and decreases as garbage collections removes unneeded DOM nodes.

See short demo here

Exploring the heap snapshot

The heap snapshot is one of three options for exploring the memory usage in Chrome. The best use of this is to preform some series of actions that are causing memory issues, then take the snapshot. Click the garbage collection icon is a good practice to force garbae collection before the snapshot is taken.

Once the snapshot is loaded, the best way to search for detached DOM nodes is to filter for Detached nodes in the top filter. Focus on the top item groups that have the highest RetainedSize that have the same order of magnitude, in the case below this would be the top three.

Image 2021-06-14 at 11 37 32 AM

Once you have identified the items of concern, we can look at each of the items by expanding the tree to find the culprit that is retaining a reference to the detached DOM node, again focusing on the items with that largest retained size.

Image 2021-06-14 at 11 44 25 AM

Selecting the first element under the top-level constructor will show what is actually retaining a reference to the detached DOM node. The tree will automatically expand to the exact retainer. This can tend to be a lot of information overload but the key is to look for signs of code that is familier to you. In the examples below it seems the main culprit is getSettingsSpecSelector and the _cache object used in the FlatObjectCache class by re-reselect.

image

From here we have identified one source of a potential memory leak, we could continue to repeat this tree exploration for other top-level items in the tree to see what other parts of our code could be retaining references to detached DOM nodes or provide more clues to the same issue we already discovered above.

Helpful tips for exploring the snapshot

Hovering over the filename, where applicable, will show you where the code is coming from to better locate and indenfiy which issues to focus on and which to ignore. Clicking the link will redirect you to the file source code in the sources tab.

Screen Recording 2021-06-14 at 12 08 07 PM

Hovering over the memory address (i.g. @1650201) will show the object preview at that address to dig deeper into the state of the code at a paticular time. This again can be helpful to decide what issues to ignore. These previews are not always available especially when refreshing the page after taking the snapshot, if you desire this ability I would advise taking another snapshot without refreshing the page.

Image 2021-06-14 at 12 00 00 PM