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 leak & onFatalError in DragDropContext #715

Closed
faiwer opened this issue Aug 17, 2018 · 6 comments
Closed

Memory leak & onFatalError in DragDropContext #715

faiwer opened this issue Aug 17, 2018 · 6 comments
Labels

Comments

@faiwer
Copy link

faiwer commented Aug 17, 2018

Hello. I started to check memory leaks in our application, and found a lot of them :(
One of them relies on react-beautiful-dnd. The leak is in the DragDropContext. Let's dive in:

  • We have class-component <DragDropContext/>
  • This class contains: onFatalError = (error: Error) => {...}
  • and onWindowError = (error: Error) => this.onFatalError(error)
  • and in componentDidMount method we make a subscription: window.addEventListener('error', this.onWindowError)
  • ... in componentWillUnmount - window.addEventListener('error', this.onWindowError);

What's wrong with it? These subscriptions retain in memory <DragDropContext/> instances forever. And all their links too, of course. They aren't removed from the memory because of onWindowError and onFatalError. Both of these methods are declared in the class-scope and have link to this object. So we have memory leak.

img_17_08_01_049a068531d
^^^ a lot of them :)

img_17_08_01_8efde6c043c

I don't know why DragDropContext needs these subscriptions, but it would be much better to remove them, or rewrite this code without memory leaks ;)

@alexreardon
Copy link
Collaborator

alexreardon commented Aug 17, 2018 via email

@faiwer
Copy link
Author

faiwer commented Aug 17, 2018

There's also 1 more memory leak. But I haven't understood them yet. This one is more intricate. It's about this code:

  var unbind = function unbind() {
    if (!isBound) {
      return;
    }

    isBound = false;
    unbindEvents(getWindow(), pointerEvents, {
      capture: true
    });
  };

bind and unBind methods in createPostDragEventPreventer.
img_17_08_01_d0ed444efcd

We again have window object and some relations with subscriptions. But.. also we have a matreshka of unbindWindowEvents :)

@alexreardon
Copy link
Collaborator

alexreardon commented Aug 17, 2018 via email

@alexreardon
Copy link
Collaborator

alexreardon commented Aug 17, 2018 via email

@faiwer
Copy link
Author

faiwer commented Aug 17, 2018

It's about the previous one. These unbind methods retain all their HTML & Fiber nodes.
img_17_08_01_cd8f2ae3390

But I can't say the certain place in the code and certain reason, that occurs this leak.

Also, what tool are you using?

I use ChromeDevTools. Their Memory tab.

  • I make a snapshot of the application
  • then I work with my application (click, click, click, click...)
  • then click to "collect garbage" icon (trash-icon)
  • then I make another snapshot
  • then I compare them and search in differences what they are and why they are :)

It's a tricky deal, but it's only what I know about how to fight with memory leaks :)

@alexreardon
Copy link
Collaborator

I can fix the first one easily. The second one will take some more investigation

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

No branches or pull requests

2 participants