Entity Framework does not release memory
SistemiData
Posts: 8
Hi,
I used ANTS memory profiler to control the amount of memory consumed by the following example code fragment (Database First - Entity Framework 6)
using(DBContext context = new DBContext)
{
var result = context.entities.where(condition);
}
I noticed that the amout of memory used, does not decrease when che DBContext is disposed.
Why is this happening?
Why Entity Framework objects remain in memory even after Dispose instruction?
I hope someone can help me.
Thanks.
Bye.
I used ANTS memory profiler to control the amount of memory consumed by the following example code fragment (Database First - Entity Framework 6)
using(DBContext context = new DBContext)
{
var result = context.entities.where(condition);
}
I noticed that the amout of memory used, does not decrease when che DBContext is disposed.
Why is this happening?
Why Entity Framework objects remain in memory even after Dispose instruction?
I hope someone can help me.
Thanks.
Bye.
Comments
If objects are remaining in memory after they've been disposed, there are likely other objects still keeping it memory. If you look at the retention graph for the DBContext object, what are the objects referencing it? If those objects are on the finalizer queue, taking another snapshot or two (to force garbage collections) after the dispose should release them from memory.
I hope that might help!
Jessica Ramos | Product Support Engineer | Redgate Software
Have you visited our Help Center?
thanks for reply.
I created a test application with contains only the following code:
using(MyEntities dbContext = new MyEntities){ }
Even if I take more snaphost to force garbage collector, object still remains in memory (about 200 KB)!
If I add a code to read or write from/to context, objects that remain in memory increase considerably (about 4 MB)!
This situation is very strange because, like you can see, there are no other code structures which can retain memory.
This could be a problem related to EntityFramework?
Any Suggestions?
Thanks,
bye.
After doing some testing, it looks like IDisposable objects instantiated in a using statement are still considered local variables of the method using it. This means while your Dbcontext object does get disposed properly after the using block ends, the garbage collector will still not pick up that object since it is a local variable of main() which is still executing. (On the other hand, having the using block in a separate method should let the Dbcontext object get disposed and GC'd once that method exits)
I hope that information might help but please let me know if I'm misunderstanding!
Jessica Ramos | Product Support Engineer | Redgate Software
Have you visited our Help Center?
thanks for reply.
According to your advice, I tried to move the DbContext code, first in another method and than in another class but nothing changes.
The code I posted is in the main method only for testing; in reality, in my real application, the DbContext code is located in another library.
I created this simple example code only to make you understand more easily the problem (this problem is systematic when using DbContext).
I still do not understand what the problem is!
Any other suggestions ?
The problem is EntityFramework, the ANTS memory profiler or something else?
Thank you very much for your help.
Bye.
I'm unfortunately not an expert myself on the EntityFramework so I'm not sure if this is expected in certain cases, but in a simple sample application I've made, the DBContext object does get garbage collected once the method that instantiated it returns. If the DBContext object is not just a local variable of the main method then it would definitely be worth looking at its instance retention graph to see what's still holding it in memory. Please let me know what you find!
Jessica Ramos | Product Support Engineer | Redgate Software
Have you visited our Help Center?
I made other tests to study the situation.
When Entity Framewok is used, despite DBContext dispose etc..., ANTS Memory profiler memory tests show large amounts of memory held by:
- Namespace: System.Reflection, Class Name: RuntimeMethodInfo
- Namespace: System.Reflection, Class Name: RuntimeParameterInfo
- Namespace: System.Data.Entity.Core.Metadata.Edm, Class Name: TypeUsage
- Namespace: System.Data.Entity.Core.Metadata.Edm, Class Name: Facet[]
- Namespace: System.Data.Entity.Core.Metadata.Edm, Class Name: EdmProperty.
- etc...
All tests always gives same results.
Could you please share some screenshots of what the instance retention graph looks like for some of those objects as well as the DBContext object itself?
Jessica Ramos | Product Support Engineer | Redgate Software
Have you visited our Help Center?
I created a simple Entity Framework memory test to make you see the strange results.
I would like to send you the whole .amp8results file with a simple description of the code, so that you can understand the situation well.
How can I send you the file?
Can you give me your mail or an address where I can upload the file?
Bye
Francesco.
Many thanks, you can send it to support@red-gate.com with #43186 as the subject.
Jessica Ramos | Product Support Engineer | Redgate Software
Have you visited our Help Center?
I just sent an e-mail with all documentation.
I'am awaiting for your answer.
Bye
Francesco
any news?
Bye
Francesco
Sorry for the delay! And apologies, as I kept thinking you mean that the DBContext object itself was still in memory after the dispose but I see in the results that it is not.
Unfortunately though, I'm still not sure myself why those other objects are remaining in memory. When you view the instance retention graphs for them, it looks like a lot of them are remaining because they are being held onto by internal framework objects. Additionally, if you actually filter down the results to see only objects that are referenced by your actual code (using the "Filter by reference>Referenced by> add namespace" option), there are not many, and almost all of those have not grown in instance # or size since the first snapshot. It seems this may just be how EntityFramework handles things.
I've actually found a stackoverflow post with a similar question, though there wasn't much feedback on the offered suggestion unfortunately - http://stackoverflow.com/questions/7573 ... age-object. In that case, someone was seeing System.Data.Metadata.Edm.TypeUsage objects growing and another user suggested using a different MergeOption. If you're able to try that, does it make any difference?
(Apologies to not have more direct advice! Our support team is not really trained on analyzing results, we're normally here to help with any problems actually getting the profiler working. )
Jessica Ramos | Product Support Engineer | Redgate Software
Have you visited our Help Center?