-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Unexpectedly high memory usage when executing large number of upsert
statements
#16912
Comments
@abrindam would you mind sharing how you profiled the memory consumption and produced the detailed graphs? I believe we're suffering from prisma-related memory issues as well, but I'm not sure if it's the same case as yours, so I don't want to hijack your issue ;) Instead I would like to gather more information first and then create a second one, potentially linking to this. Oh and there are already quite a few memory-related issues here and over at prisma/prisma-engines. Many of them revolve around |
@Gerrit-K Glad to hear I'm not the only one. As far as |
@Gerrit-K I just realized I missed your first question! As far as producing these graphs, it was pretty low tech - good old fashioned
This seemed to be the least invasive way to profile. I tried attaching debuggers and other similar things but they had side effects like brutally slowing things down. So I just had the process periodically log out as above, and then used text editor magic to turn them into a spreadsheet. |
@abrindam ah thanks! I was considering this as well, but I was wondering whether I missed some cool tool ;) But good ol' spreadsheet works as well. Until now, I was only using metrics from prometheus, but their granularity was too coarse for my taste for debugging this. I think I'll build something similar and see if I get any new insights. Regarding the update from you on the statement cache: yeah, I was assuming you were already aware of that and I'm sorry that it didn't help 😕 What I find interesting, though, is that the "no cache" versions seem to be even worse than the regular ones, which is somewhat counterintuitive for me. I would assume that having the cache will basically increase the memory a bit for the benefit of reduced CPU consumption (or overall speed). Your graphs however, suggest the opposite (or I misread them 😅 ) |
No cache means additional work, as nothing is reused. |
I am facing the same problem. The application inserts about ~20k-50k rows into the database (PostgreSQL) every 15 minutes. The RSS memory goes up while the heap stays stable. Reducing the number of inserts helps memory usage. This is my Prisma installation details:
|
Same issue here. The affected application consistently upserts records in batches of 1000 and this is how the memory usage looks like (memory only goes down after the application runs out of memory and restarts): The problem only occurred after updating I was able to reproduce it locally with this code and tested it with different versions of Prisma: async upsert(count: number) {
for (let i = 1; i <= count; i++) {
await Promise.all(
ids.map(async (id) => {
const data = { id, name: randomInt(100000).toString() };
await this.prisma.test.upsert({
where: { id: data.id },
create: data,
update: data,
});
})
);
}
} Here are the results: Environment (local)
Prisma Version (local)
|
Do we have any updates here? |
No. |
As always, thank you for developing Prisma. We use Prisma well. I wonder if there is any investigation into this memory leak issue. We are unable to push the prisma version beyond 4.8.1 because the memory leak slows down the application performance and causes the application to crash periodically. It's unfortunate that we can't use a version higher than 4.8.1, as Prisma continues to release great new features. |
What would be helpful is a standalone reproduction of the problem that we can easily run by following some instructions to see the problem in action. That will make it much easier for us to get started here. |
https://github.com/cashwalk/prisma-issue16912-reproduction Please check this repository. Thank you. |
This comment was marked as off-topic.
This comment was marked as off-topic.
@janpio Hi. I wonder if there is any discussion or plan to solve this memory leak issue. |
Yes, there is discussion and a plan to work on fixing this, but no ETA when we get to it I could communicate - sorry. |
It's good that there was a discussion on this issue. Thank you for answer. |
Unfortunately there were reports of this problem with Node 18 as well above, so while I am happy that fixed it for you @abrindam we still need to investigate and figure this out. |
Thank you so much @backend-sungjee for providing a full reproduction that we can just run. Doing that now. In the meantime a question to everyone:
And an observation: Can some of you try to use https://github.com/cashwalk/prisma-issue16912-reproduction to also reproduce on your environment? That would be super helpful to see if the reproduction is reliable and clear. (Background: Right now to me it does unfortunately not look that clear on the first runs...) (@livthomas I hid your comment as any memory problems of the binary engine are unrelated to this. Please open a separate issue and provide more information. Thanks.) |
For our service, we were using AWS instances created by AWS elastic beanstalk, with the instance directly executing node. |
It's my local environment OS: I'm sorry, |
@janpio We primarily use the library engine. We only switched to the binary one to see whether the memory leak is really in the Prisma engine and not in our app. And the memory is steadily increasing regardless of the engine type. We run our apps in DigitalOcean Apps Platform: We previously used Node.js v16 and the problem was visible there as well. |
upsert
statements
Hey folks! I was able to confirm the repro that @backend-sungjee linked and I was also able to confirm that that issue disappeared when updating from Node 16 -> Node 18+ Prisma
|
Hey @abrindam Did you get a chance to take a look at my previous comment? It'd be helpful for us to move your issue forward. Without further information, we'll have to close this issue. |
Hello here, it's been a while since this issue was created, we tried our best to investigate and reproduce based on the issue and comments, and we think it's now time to close this issue. First, note that Prisma 5 was released in July 2023 and 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 the reproduction from @backend-sungjee and also in a different issue #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 minimal reproduction, we will be happy to investigate and try to reproduce. As a general note, when creating an issue, 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
The application I'm working on ingests bulk data and upserts it into a database using Prisma. The scale of this data is large, but not huge: approx 250,000 records, with each record being fairly small (6 strings, a float, and a datetime). We're looking to run this process on as small hardware as possible, so I've been investigating running this in a memory constrained environment.
What I've found is that our application requires around 1.2GB of memory in order to perform this upsert process. Upon investigation, I found that if I temporarily disable the single line that actually upserts the data (
prismaClient.upsert()
), the memory usage drops dramatically to 400MB, implying Prisma is responsible for 2/3 of our memory usage.Further analysis has shown that the memory jump occurs pretty rapidly, within the first 50,000 records or so, at which the memory usage reaches 1.2GB and stays roughly in that range for the rest of the processing. For this reason, I would not classify this as a "leak" - the memory usage does eventually plateau. However, you still need to upsert a fairly significant number of records to see the problem - only 1,000 or so won't trigger it.
The following graph shows the JS Heap usage and the overall process memory usage (RSS), with the single upsert statement enabled and disabled:
As you can see, the JS heap usage actually looks pretty reasonable in both cases, but the process total memory is significantly higher with the statement enabled. This suggests the memory is likely being consumed by the Prisma Engine.
A couple of other tidbits of info:
upsert
with anupdate
did not noticeably affect the memory usage either wayupsert
with anselect
also showed abnormally high memory usage but it was reduced to approximately 2/3 of what it previously was.--max-old-space-size=512
to ensure aggressive garbage collection. If this flag is removed, the same problem happens, but the graph above doesn't look as nice due to GC lag.Overall, I'd just love to know if I'm missing something entirely, if I'm nuts, etc, or if this seems like a real problem!
How to reproduce
Expected behavior
Memory usage should remain relatively low and not climb dramatically around 50k records. I would expect the cost of using Prisma to be no more than 200MB in this situation (correct me if I'm totally wrong about this). At minimum, I would not expect the memory usage to be related to the total number of records upserted.
Prisma information
(names of objects/fields altered for privacy)
(I also tried it without
$transaction()
, same result)Environment & setup
Prisma Version
The text was updated successfully, but these errors were encountered: