jest: Memory Leak when running multiple test. Especially with --runInBand

šŸ› Bug Report

Hi. Iā€™m seeing a memory leak while trying to run a basic autogenerated ( with ā€œng g c my-testā€ and "ng g c ā€œmy-test-2ā€) Angular component. If i run jest with --detectLeak , i get messages saying that there are leaks. If i run jest with --runInBand , i see heap size going up ā€¦ when i add enough of those ā€œblankā€ tests or reduce the size with --max_old_space_size= , I run out of memory. From what i was able to see the teardown (between tests) is not happening properly until it finishes the very last test. Any suggestions on what to do? versions: jest: 23.6.0, jest-preset-angular: 6.0.1, jest-leak-detector: 23.6.0, zone.js: 0.8.26

To Reproduce

Steps to reproduce the behavior:

  1. create a bunch of Angular components with tests using ā€œng g c my-test-cmp-1ā€, ā€œā€¦cmp-2ā€, etc
  2. run ā€œjest --runInBand --logHeapUsage components/ā€ so it runs all the tests
  3. observe heap size grow as many times there are tests. Also, if you take a heapdump, you could see a bunch of ā€œglobal > proto :: Windowā€ entries. One for each test.
  4. observe that environments for each test are not torn down until all test complete. If you have enough of those tests or if you lower allocated memory with --max_old_space_size, youā€™ll it running out of memory

Expected behavior

I think the proper behavior would be to tear down environments after a test file each test file is done and allow garbage collector to do itā€™s job.

Link to repl or repo (highly encouraged)

Please provide either a repl.it demo or a minimal repository on GitHub.

Issues without a reproduction link are likely to stall.

Run npx envinfo --preset jest

Paste the results here:

System: OS: macOS High Sierra 10.13.6 CPU: x64 IntelĀ® Coreā„¢ i7-8559U CPU @ 2.70GHz Binaries: Node: 8.12.0 - ~/.nvm/versions/node/v8.12.0/bin/node npm: 6.4.1 - ~/.nvm/versions/node/v8.12.0/bin/npm npmPackages: jest: 23.6.0 => 23.6.0


About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 12
  • Comments: 21 (6 by maintainers)

Commits related to this issue

Most upvoted comments

To run the global.gc() on each test, you just need to put afterEach (or afterAll) inside a setupFilesAfterEnv. This way, the function be called inside each test and after Jest module is initiated.

Inside jest.config.js:

{ 
  setupFilesAfterEnv: [
    '<rootDir>/force-gc'
  ]
}

Inside force-gc.js:

afterEach(() => {
  if (global.gc) global.gc()
})

No need to create a particular function on Jest.

I canā€™t provide example code which repeats this issue easily, as the code isnā€™t licensed such that I can share it, but my team sees an issue similar to this. jest consumes tons of memory and keeps eating memory until it runs into swap space. Weā€™ve been able to fix this by manually running global.gc() in afterAll blocks.

It looks like something is stopping the garbage collector from running. It might be nice to have a setting in Jest to force the garbage collector to run when thereā€™s only a specified percentage of available memory remaining, or something like that.

Our team is experiencing issues as well. I also canā€™t post the repo due to proprietary tech. It appears to be related to setup/teardown of internal jasmine. Iā€™m seeing the same objects populate memory over and over again.

https://share.getcloudapp.com/4guxKGwn https://share.getcloudapp.com/kpumJvLL

Steps to reproduce:

  1. Run the node inspector with Jest and log the usage: node --inspect-brk --expose-gc ./node_modules/jest/bin/jest.js --runInBand --logHeapUsage
  2. Open chrome://inspect
  3. Click the link to inspect the node instance
  4. From the Sources tab, click the Play icon in the top right to Resume script execution. You will now see the Jest console begin running the tests. You can also pause the script execution with the Pause icon to stop Jest
  5. Take heap snapshots
  6. Profit

--expose-gc

We were struggling with java heapsize problems for the last month, with karma/jasmine and jest respectively. After several negative attempts we found one major problem in our test suites - we imported a module in almost all tests, which itself imported lots of google material modules. That caused all tests to run slow (compared to now) and lead to the heap size problems. We restructured our test suites (do not import large modules, mock everything that is not part of the current class under test, use TestBed only if necessary, do not compile the components, add NO_ERROR_SCHEMA etc). Now, we do not have heap space problems under karma/jasmine, and the tests run, as they should, very fast.

Unfortunately, we still get heap space disconnects in jest. Donā€™t know why.

Our team was able to stabilize heap size using this particular approach: https://github.com/integrations/slack/pull/895

We definitely have a memory leak but the leaks are not as significant as the ones we were previously experiencing. I hope this helps until we get a long term approach šŸ‘

Turns out this issue is not because of our test suite. Thereā€™s something odd going on with Jest retaining multiple instances of files: https://github.com/facebook/jest/issues/7874

If it doesnā€™t affect performance negatively, then Iā€™m in

While the leak is in user code and not jestā€™s code, I wonder if we should run the gc automatically after a run is complete? We already have code for it: https://github.com/facebook/jest/blob/084508290f4a90b28c3190021d3358ab1f753c3f/packages/jest-leak-detector/src/index.ts#L57-L68

Thoughts @jeysal @thymikee?

Yeah sorry should have mentioned itā€™s a Node option, not a Jest option

@jeysal well, this is not so obvious actually, because you can run jest like that "test": "jest

but in order to use this option, it should be run in this way "test": "node --expose-gc ./node_modules/.bin/jest