-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
How to release Mongoose model from memory? (memory leak) #2874
Comments
Connections keep track of their associated models in the |
Deleting models seems to free about half of the eaten memory, with all amounts tried. 100k without
100k with
Any ideas how to free it completely? |
I think some |
There's no good way to do that AFAIK but as far as freeing up memory goes I think |
Mongoose v. 4.0.1 |
These lines did the trick and got all my memory back:
|
I see, so that's all the places where it's tracking the collection data. Thanks for investigating, very useful information :) |
I have a very similar issue with trying to retrieve large data sets and the memory growing rapidly on each retrieval from the client. Code in my controller is as follows: 'use strict'; exports.getUser = function *() { How can I implement something like above: when I try and do I get the following error and where, to free up memory once the data have been retrieved. I only care about retrieving the data, not saving it again afterwards. Thanks for any assistance. |
Try: delete mongoose.models['User'];
delete mongoose.connection.collections['users'];
delete mongoose.modelSchemas['User']; |
The other solution that works perfectly for me is to not use global moongoose, instantiated with use the following instead:
so that you can manage references to Moongoose() instances just like any other objects and it will be garbage collected when needed. |
Good suggestion @illarion 👍 |
@illarion @vkarpov15 That seems like a really good solution to the same problem I have as OP. Two questions:
Thanks heaps! |
|
Leaving this snippet here in case anyone else finds it useful. It's mostly just a variation of what's already been discussed. We create our models directly on connection objects, and our Jest tests were quickly chewing through available memory. We were able to programmatically remove references to all models/connections with this code in an mongoose.connections.forEach(connection => {
const modelNames = Object.keys(connection.models)
modelNames.forEach(modelName => {
delete connection.models[modelName]
})
const collectionNames = Object.keys(connection.collections)
collectionNames.forEach(collectionName => {
delete connection.collections[collectionName]
})
})
const modelSchemaNames = Object.keys(mongoose.modelSchemas)
modelSchemaNames.forEach(modelSchemaName => {
delete mongoose.modelSchemas[modelSchemaName]
}) |
@QuotableWater7 do you have a repo example of this with jest? @vkarpov15 should mongoose provide a helper to cleanup models from memory? any other place where memory can leak from mongoose? related to jestjs/jest#6787 |
Opened up a separate issue to track ☝️ |
Can someone please elaborate on @illarion suggestion. My current code that is causing leaks:
I have 64 models in my system defined on the mongoose instance. I only want one connection to the database. In that suggestion, wouldn't I be creating a new connection for every API request that comes into my server? That doesn't sound right. What I've been doing is using a single call to mongoose.model to get each model in my system. Then I hold on each model in the house namespace and never get rid of until my server restarts. I'm guessing this is the cause of my massive memory leak. I need a way to get a new instance of a model for every API request and fetch or write the data I need from the database, then get rid of the model. I would appreciate some guidance because this leak has become unsustainably expensive monetarily. Would switching
help by creating a new instance of the model every time another file does |
I tried doing this after every request, and it slowed down my server requests considerably:
I guessing it's because the model has to be created before every request. It'd be great if there was a definitive tutorial on how to build an web app using mongoose without causing the memory leaks that have been shared here. |
This is only needed for tests You should create a single mongoose connection per server and you would be good to go |
Hmm, if it's a problem for tests, then it must also be a problem for the thing you're testing, the server, no? |
I found the leak. I'm happy to report that it is not mongoose. Thanks for the help everyone who contributed to this thread. |
@Lwdthe1 because it isn't a leak, you typically don't delete a model once you've created it. Creating a new model using |
#2874 (comment) |
I know this is a Closed issue, but I would like to add what we discovered recently. BLUF: if you are repetitively building a model using model.discriminator(), the schema is getting exponentially bigger due to schema._originalSchema = schema.clone(). Against recommendations, we are doing open/close with each request instead of caching connections. This is because our multi-tenancy adds an additional level of security in that each tenant gets their own database with their own set of user credentials. Mongoose useDb() did not seem to support that, nor any other mod/hack I could find on Google. (Note: I have since modified a library called mobgoose to cache down to that level and may use it going forward). We initially tried deleting everything under the sun as suggested above to no avail. If you use connection.model(), we could get things to clean themselves up. However, we were using model.discriminator(). Looking inside the mongoose library code and seeing how the Model.discriminator() and Schema prototypes work, we see a lot of clone() calls. The exponential memory leak seems to come from schema._originalSchema = schema.clone(). Our current solution, if we are to continue with open/close per request, is to re-generate the Schema on each call too. Mucking around inside the Schema to delete individual properties seemed too risky, and this gets us past the current issue while we explore a better solution going forward. |
@weichtg3 that's an interesting use case, thanks for elaborating. We'll look into whether we can get rid of |
There is no |
@snowshoes just use |
How to release the model from memory after accessing it? I'm using
global.gc()
with--expose-gc
option to see that this is eating my memory.The following code creates 10000 collections:
The memory usage is increasing as collections are created and the memory is never released:
Any ideas how to purge the model from the memory manually without closing the connection?
The text was updated successfully, but these errors were encountered: