-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
jest-circus memory leak #8816
Comments
Thanks for the reproduction! It might male it easier to track down - we currently oom with circus on CI, sp there's definitely an issue here. @scotthovestadt did you look into it yet? |
No worries! Thanks heaps for looking into this! I dug into this a bit more, used Unfortunately, commenting out the equivalent line on Some other things I tried, cumulatively, were:
Even with all of those changes combined, I was still seeing the same amount of memory leaked. 😕 |
Yeah, that commit was reverted an re-landed in #6176 due to memory leaks |
Ah, that is super helpful. Thanks for that! I looked again after #6176 and, you guys may already be aware, it looks like the next memory leak was introduced with this commit: c5994de. I think it may be this line: https://github.com/facebook/jest/blob/94067089dd25c77463e24e981fe979fb6cc0b2fb/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts#L28 Calling I apologize for the crudeness, but here is a simplified example of the logging pattern that I was using followed by some sample outputs: // jestAdapter.ts
const FRAMEWORK_INITIALIZER = require.resolve('./jestAdapterInit');
const jestAdapter = async (
// ...
): Promise<TestResult> => {
global.gc();
console.log(`1. START ${filename}: process.memoryUsage().heapUsed MB`);
const {
initialize,
runAndTransformResultsToJestFormat,
} = runtime.requireInternalModule(FRAMEWORK_INITIALIZER);
global.gc();
console.log(`2. AFTER INVOCATION ${filename}: process.memoryUsage().heapUsed MB`);
// ...
global.gc();
console.log(`3. END ${filename}: process.memoryUsage().heapUsed MB`);
return _addSnapshotData(results, snapshotState);
} Output: 1. START index-44.jest.js: 220.00968170166016 MB
2. AFTER INVOCATION index-44.jest.js: 222.1803207397461 MB
3. END index-44.jest.js: 222.3431625366211 MB
PASS __sandbox__/__tests__/index-44.jest.js (222 MB heap size)
1. START index-28.jest.js: 222.53646850585938 MB
2. AFTER INVOCATION index-28.jest.js: 224.7444076538086 MB
3. END index-28.jest.js: 224.8832015991211 MB
PASS __sandbox__/__tests__/index-28.jest.js (224 MB heap size) |
That's really interesting, thanks! Seems like |
I just started getting into the |
@bcmarinacci Amazing findings! I also tried attacking error stacks and the sourcemap install but (also) wasn't able to see this resolve. I have an idea what might be causing this with the framework install. I wonder if the runner state, which is placed on a global, needs to be cleaned up... It really wouldn't surprise me. I'll spend some time tomorrow on this. Thank you! |
Is there any progress on this one? |
I looked into this a bit now as the leak is really starting to become an issue. Unfortunately, I think it has always leaked - in the reproduction from the OP it doesn't actually test circus in the non-leaking v22 - the {
"jest": {
"testRunner": "jest-circus/build/legacy_code_todo_rewrite/jest_adapter.js"
}
} It's not actually enough since that file does // circus-runner.js
module.exports = require('jest-circus/build/legacy_code_todo_rewrite/jest_adapter.js').default; And doing that shows that it leaks in 22.4 as well. |
For each test passed its Runtime and Environment is still allocated in memory. |
I've tried to delete a whole bunch of assignments (including removing the whole of I also tried to reset the runner state in mentioned in #8816 (comment) without much luck at getting it to make a difference |
The only way to stop the leak I found was to return a fake result in the top of Its really hard to recognize which assignment of which object is being leaked, because almost everything is being leaked and inter-related. My best guess is a reference (indirect) to the Runtime is held by the previous run either in its result (which would be very rare), or in |
That function should do essentially the same as this function in Jasmine, which doesn't leak: I was also unable to track down where circus caused some stuff to be retained while the Jasmine runner was able to make it GCed. (Some memory increase per test is expected of course as we store test results as they complete.) |
The reproduction only reproduced the leak when running in band, which has now been fixed. Landed a few other leak fixes in 25.5.1, so hopefully things are better now. Might be other leaks, but new issues for those would be good. I'm guessing worker runners worked since it serializes from workers to parent |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
🐛 Bug Report
First off... thanks heaps for creating and maintaining Jest. 🙏 JavaScript testing is in a better state because of all you do! 🃏
It looks like a regression was introduced between versions
22.4.4
and23.1.0
of Jest Circus that is causing a rather substantial memory leak (I wasn't able to run any tests with errors on any versions between those two versions):$ npm run jest-circus PASS __tests__/index-21.jest.js (24 MB heap size) ... PASS __tests__/index-79.jest.js (251 MB heap size) PASS __tests__/index-49.jest.js (253 MB heap size) PASS __tests__/index-65.jest.js (256 MB heap size) PASS __tests__/index-73.jest.js (258 MB heap size) Test Suites: 100 passed, 100 total Tests: 100 passed, 100 total Snapshots: 0 total Time: 13.991s Ran all test suites.
I had a look at #7274 (comment) as well as #6965. I added
this.stack = this.stack
to https://github.com/facebook/jest/blob/master/packages/jest-util/src/ErrorWithStack.ts (via https://github.com/facebook/jest/blob/master/packages/jest-circus/src/index.ts) andthis.stack = this.stack
after everynew Error()
invocation in https://github.com/facebook/jest/blob/master/packages/jest-circus/src/utils.ts, which didn't seem to impact the leaks at all.Other than narrowing down the version that introduced the regression and trying what was mentioned in #6965, I haven't really had time to make any more progress. I also noticed #7274 but that seemed to be focused on memory leaks from
graceful-fs
, which I confirmed independently, so I thought I would create a new issue that focuses purely onjest-circus
.To Reproduce
I created a sandbox repository with a simple test and 100 test files. I then ran the tests with
jest-circus
as well as the default runner for (matching) versions:24.8.0
,23.1.0
, and22.4.4
and recorded the results: https://github.com/BuildingConnected/jest-circus-memory-leak.Expected behavior
The memory footprint when running tests via
jest-circus
should match that of the default test runner.Link to repl or repo (highly encouraged)
https://github.com/BuildingConnected/jest-circus-memory-leak
Run 100 test files:
Run
npx envinfo --preset jest
The text was updated successfully, but these errors were encountered: