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
Possible memory leak when running tests with Jest #17171
Comments
Hi @dwayneyuen.
Could you try doing all of the things at the same time (calling |
I have the same issue and have tried to use I'm also seeing the same patterns when exploring the heap snapshot; loads of repeated strings containing the full module code. To really get to the bottom of this, we will have to create a minimal example that can be confirmed to leak, but that is more work than I have time to put in, so I'll just increase the memory of our CI machines 🙈 |
So I looked a little more into it, and I could alleviate this issue somewhat by downgrading to node 16.10.0. As mentioned in jestjs/jest#11956, this issue has started showing up with node 16.11.0 and appears to be present in this and all later versions. With node to 16.13.0, the heap size started at ~700MB and grew up to ~2500MB at the end of a test run. After downgrading to 16.10.0, the heap still started at ~700MB, but never grew above ~1400MB and even went down after a few tests, with a final size of ~1200MB. |
@iFreilicht What version of Prisma are you using? There used to be a memory leak on prisma side but we fixed it in 4.1.0. As long as you are using library engine and calling |
I'm using |
We are also experiencing this very same memory leak. We see the same huge repeated strings inside our heap related to Prisma which is crashing our APP in Github Actions CI runners. Prisma Version: Have |
Thanks for the tips - we just tried this and it didn't seem to make a difference. For what its worth, I can see this being an inherent issue with Jest and Prisma may trigger it if it uses an above average amount of memory or something. |
Isolated reproductions are very welcome @andrewmclagan. |
I have the same issue and I'm using Node 14 with Prisma 4.3.1. If I run a test that instantiates the client (i.e. |
Ditto.
@prisma/client version: 4.12.0 If I remove the |
I am also experiencing this. Is there anyway I can help the investigation of this issue? |
@janpio I put this very minimal repo together to demonstrate that simply initializing a We use Prisma in all of our repos but did not encounter an issue until quite recently in one of them with a lot of tests. We've discovered that our current Jest suite accidentally initializes a new Adding this code to our jest.setup.js causes jest.mock('@prisma/client', () => {
const actual = jest.requireActual('@prisma/client');
return { ...actual, PrismaClient: class { $on() {} } }
}); Edit: Just to add to this, I followed the same steps the original poster did and had the exact same symptoms with the strings taking up all the memory. When I track the heap, it grows and shrinks as memory is allocated and GCd. When I allow the |
same issue here. the moment i instantiate PrismaClient, jest complains about a memory leak. on node v20.3.1. |
Same issue here |
I've done a bit more experimentation locally. I've tested with all versions of 4.x.x and a handful of 3.x.x. Here are the results I have collected from my example repo:
Interestingly, this list makes it look like
Given that I tested against |
I posted this answer on stack overflow and I'm posting it again here. Me and my team were having a memory leak using jest 29.x and node 18.x. The test suite would run, have a memory leak and make node crash at 2GB of memory usage. Increasing RAM memory allocated to node was not an option, since the test suite would increase in number of tests making it eventually fail, besides, 2GB is already too much. Practical SolutionThis answer IS NOT a direct solution to the problem, but this turns the problem potentially harmless and we used lots of hours to reach it. First thing you need to do is to set this config on your module.exports = {
...
workerIdleMemoryLimit: '512MB',
...
} I chose 512MB, but choose your value with some space left like This alone itself will never allow your test suite to crash and the problem is pretty much solved. Lowering the total amount of RAM usedNow, as important as not making node crash is using reasonable amount of RAM to run your tests. Every consideration from now on decreased the total amount of RAM used in a full run of the test suite. 1. Run jest using this config --expose-gc --no-compilation-cache:node --expose-gc --no-compilation-cache ./node_modules/jest-cli/bin/jest.js --logHeapUsage The "logHeapUsage" will log the memory usage so you can check the improvement. 2. SWC as a transpilerIf you are using typescript, use SWC as a transpiler to JS instead of tsjest, it's way faster, saved us tons of memory since the transpilation process was our most memory intensive process. 3. Forcebly call the garbage collector after all tests of a test suite.
This in principle shouldn't be necessary, but somehow jest is not doing it as much as it should. Using this, we reduced the total amount of memory per test suite executed. 4. Find libraries with import * as ...Some libraries like aws-sdk v2 will try to import everything even if you are using just a tiny fraction of it's code. If you look where the import happens in the lib, everything is imported to a single file, than you import from that file and all that useless stuff sits in your memory. To solve it, just trace the exact location where the asset you want sits and import directly from there. In the case of aws-sdk you can also use aws-sdk v3 which solves this problem. 5. Use tiny libraries.Sometimes we can't just replace libraries, but changing from class-validator to a tiny library like zod helped. 6. Update your libraries.In our case updating Prisma ORM from 4.10 to 5.0 made wonders. The new prisma made our test suite run 2.6x faster and use way less memory. Final ResultJust so you can take some numbers into perspective. Our test suite would require 1.1GB of RAM on startup, every test suite created a memory leak that increased the total amount of memory in 100MB. Each test suite took 15 - 10s to run. After 10 tests node would crash.
We went from a crashing test run that would start with 1.1GB of RAM usage and climb 100MB per each test suite to a never crashing one (due to the solution I first stated on the jest config) that would start with 30MB and climb 14MB per each test suite executed. If 512MB was ever reached, it would immediately decrease to 30MB again and start to slowly climb again. I really hope that helps anyone struggling with that. |
Hello! I've also experienced this weird memory leak when running tests with jest. What I did in my case was to create 400 separate, identical, bare bones tests (e.g. empty describe and it blocks), and only run those using Then, gradually add more logic to the tests (keeping them identical). e.g. add a simple beforeEach hook / import a simple module in the tests, and closely monitor what happens to the heap memory. For me everything behaved fine until I started mocking modules. When mocking module 'src/.../foo' like this: import { foo } from 'src/.../foo'
import bar from 'src/.../bar'
jest.mock('src/.../foo')
describe('bar()', () => {
...simple hooks...
it('should return ...', async () => {
jest.mocked(foo).mockResolvedValue(true)
const result = await bar()
expect(result).toBe(true)
})
}) the memory leak immediately occurred... After trying different things, I learned this way of mocking module 'src/.../foo' eliminates the memory leak in my case: jest.mock(
'src/.../foo',
() => ({
foo: jest.fn().mockResolvedValue(true),
})
) I ended up visiting all unit tests and using a factory function for every Hopes this helps! |
@pedrodardengo using I'm executing the tests with
Edit: it seems to work when I use it as a command line arg instead of putting it in my jest config, i.e. adding |
Hello here, it's been a while since this issue was created, and after investigating this we came to the conclusion that we could not find a memory leak, based on the original issue. Like we found in #13575, about Jest Note that Prisma 5 got big performance improvements, like the internal protocol switch, which uses less RAM, for more details see https://www.prisma.io/blog/prisma-5-f66prwkjx72s Additionally, we actually found a memory leak in #17925, but it is only happening with Node.js v16, which is now End-Of-Life. If you have a reproduction where a memory leak can be observed with a recent version of Prisma, please open a new issue with a reproduction, we will be happy to investigate and try to reproduce. As a general note, let us know if what you see is excessive memory usage or something that looks like a memory leak.
I hope I can create a code template in the future with some guidelines to help with identifying potential memory leaks in the future (to be done). |
Bug description
We have a memory leak when we run a number of tests (~100) with Jest which eventually leads to a crash. Each test leaks around 40-50 mb of memory. While we can't positively say that Prisma is at fault, we have some data to support that hypothesis.
When we take a heap snapshot of early in the test run and late in the test run, we find that
Code
andStrings
grow disproportionately larger relative to the other segments.Early in the run:
Late in the run:
If I sort by shallow size descending and expand the strings segment, we find that the Prisma runtime index.js is near the top and repeated many times (note the repeated
2 444 640
shallow size):We find the same if we expand compiled code (note the repeated shallow sizes of
257 312
):So while we can't positively say Prisma is the reason for our memory leak and eventual crash, it does seem to be the dominator in the segments that grew disproportionately. We use Prisma 4.5.0, NestJS 9.0, and Jest 28.1.2 and set up our prisma client using this recipe. The memory leak occurs whether we run the tests in parallel or in serial.
Happy to share more information if it would be helpful! Cheers!
How to reproduce
node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage
Expected behavior
Expect heap size to remain relatively consistent or at least not grow to the point of crashing
Prisma information
// Add your schema.prisma
// Add your code using Prisma Client
I can't share the schema. The prisma client is set up using the NestJS recipe here: https://docs.nestjs.com/recipes/prisma#use-prisma-client-in-your-nestjs-services
Environment & setup
This also occurs on github actions using
ubuntu-latest
Prisma Version
The text was updated successfully, but these errors were encountered: