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

QueueScheduler memory leak #754

Closed
andrevmatos opened this issue Sep 30, 2021 · 1 comment
Closed

QueueScheduler memory leak #754

andrevmatos opened this issue Sep 30, 2021 · 1 comment

Comments

@andrevmatos
Copy link

andrevmatos commented Sep 30, 2021

Do you want to request a feature or report a bug?
bug

What is the current behavior?
Epics operators subscriptions create several QueueAction instances, which are held in OperatorSubscriber's _teardowns array and never freed. Worse, these objects's work member can hold contexts from operators, which often include pretty heavy objects, like state, which quickly fill up memory on large applications.

On our real life application, while stress-testing it, we've seen Node process dump core with 8GB+ memory usage (while the base memory usage lays below 40MB). We thought some of the native libraries there were causing the leak, but we managed to create a standalone repro also demonstrating it.

If the current behavior is a bug, please provide the steps to reproduce and a minimal demo of the problem using JSBin, StackBlitz, or similar.
I've created a standalone NodeJS app, which can be debugged with Chrome DevTools Inspector:
https://github.com/andrevmatos/redux-observable-leak-repro

As is stated in README, one can reproduce with:

yarn
yarn build
node --inspect-brk index.js

Then open Chrome/Chromium in chrome://inspect , click on the waiting instance, press F8 to run the code, then go to Memory tab and take a Heap snapshot to see the leaked objects.

Example (notice 150k+ QueueActions):
Screenshot_20210930_152955

What is the expected behavior?
Even if the range is created synchronously, as soon as the actions are dispatched and handled, the objects, variables and contexts should be freed. Notice the repro keep only the latest action payload (at most ~50kb) in the state, the repro does NOT keep any explicit reference to any action, state or payload beyond the latest (as a standard redux example), and no explicit subscription is made, therefore everything created during initial processing should be garbage-collected.

Some things I've tried:

  1. replacing the range observable with lazy generator or mergeMap to async/Promise instead of sync array => bug still occurs
  2. manually editing redux-observable/dist/cjs/createEpicMiddleware.js and removing all usage of uniqueQueueScheduler, subscribeOn and observeOn => bug does not occur

Which versions of redux-observable, and which browser and OS are affected by this issue? Did this work in previous versions of redux-observable?
NodeJS 14.x
yarn 1.x
rxjs@7.3
redux-observable@2.0.0

@andrevmatos
Copy link
Author

andrevmatos commented Oct 1, 2021

As per ReactiveX/rxjs#6624 (comment) , this actually already got fixed by ReactiveX/rxjs#6559 and ReactiveX/rxjs#6562 , just not released yet. Closing this.
Edit: released as rxjs@7.3.1

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

No branches or pull requests

1 participant