Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leaks #2899

Open
bhousel opened this issue Jan 7, 2016 · 2 comments
Open

Memory leaks #2899

bhousel opened this issue Jan 7, 2016 · 2 comments
Labels
performance Optimizing for speed and efficiency

Comments

@bhousel
Copy link
Member

bhousel commented Jan 7, 2016

Opening this issue because I dug into it a bit, but don't have more time this week.

iD leaks memory pretty bad. This relates to #2743 - performance as a user makes many edits - but the causes and solutions are different.

We expect iD's memory usage to grow in certain ways as a user edits:

  1. Scrolling the map downloads more entities from OSM which get added to the base graph.
  2. Each edit makes a new immutable Graph, and they get stacked up in history.
  3. Changing an Entity makes a new immutable Entity.
  4. Caches (Graph's parentWays/parentRels/childNodes, History's rbush, Features' internal cache)

But we expect memory to be garbage collected at other times. D3 should remove() DOM elements from exit selections as things are no longer needed. This applies to:

  1. SVG elements on the map
  2. Everything in the inspector / entity editor / sidebar
  3. Modals

We are sometimes lax about calling that remove, and other times remove can't do its job properly because of references elsewhere in the code.
screenshot 2016-01-07 12 31 26

In that screenshot from the Chrome heap profiler, red things are DOM elements that are detached but can not be garbage collected, yellow things are DOM elements that we still refer to somewhere.

The screenshot shows that the event handler which toggles the raw tag editor is still holding a reference to a D3 selection of the raw tag editor itself. So D3 remove() detached it from the DOM, but it stuck around in memory anyway.

A good summary of what's happening can be found on the Chrome dev tools page, especially this graphic:

detached-nodes

This is an easy problem to study, because all you need to do is take a heap snapshot, select/deselect a thing on the map so that the entity inspector shows and then clears, then take another heap snapshot and compare the two. But that's just one memory leak in one UI element, and the bigger problem is that this is a widespread "death by a thousand cuts" antipattern everywhere in iD.

We need to be smarter about removing stale references to things in:

  • D3 selections
  • Event handlers
  • DOM element __data__
  • closures that mash all of the above together

Also related: d3/d3#1041
mbostock's take on this: "well, duh"

@bhousel bhousel added the performance Optimizing for speed and efficiency label Jan 7, 2016
@jfirebaugh
Copy link
Member

The presence of detached DOM nodes in memory is not in and of itself a bug. There are cases where for performance reasons, retention is intended, so that the DOM nodes can be re-attached when the UI component becomes visible again, rather than rebuilt from scratch. I believe this is the case for some of the things in the "inspector / entity editor / sidebar".

@gy-mate
Copy link

gy-mate commented Jan 27, 2024

Unfortunately this is still an issue (using Safari 17.3). iD uses 4+ GB of memory after opening the editor, making & saving edits at different places and closing the editor (going back to OSM Carto) several times without closing the tab itself.
Screenshot 2024-01-27 at 13 20 24
This makes iD unresponsive for several seconds after a single click on an element.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Optimizing for speed and efficiency
Projects
None yet
Development

No branches or pull requests

3 participants