I have a relatively large Entity Framework model (approx ~300 tables) for which I pre-generate views to improve query/application performance.
When the application is under minimal load I experience gradually increasing memory consumption within the application over the course of 6-7 hours. Upon reaching approx. 4GB, the application pool is reset and the process repeats.
Figure 1: Showing application memory consumption over the course of 8-9 hours
This application uses a variation of the repository pattern and ensures that instances of my ObjectContext re instantiated and destroyed in the shortest time feasable for each transaction. I also implement IDisposable on all repositories/interfaces in order to clean up any resources.
I have carried out extensive tests on the application with memory profilers such as Red Gate's ANTS profile, WinDbg and others and have so far been unable to determine the exact cause of the memory issue, however have noted the below:
A Red Gate ANTS profiler test shows that there are too many Entity Framework MetadataWorkspaces being created, causing lots of extra object mappings and associated SQL command text to be held. There’s also single instance of myEntities in a particular repository which contains a MetadataWorkspace and the InitializerMetadata cache contains 351 entries at the end of a stress test. These 351 entries each have another copy of myEntities, each of those has a MetadataWorkspace, and each of those has hundreds of object mappings.
My core solution is structured as follows:
If anybody is able to provide any pointers, I'd be very grateful.
We are automatically assuming that the problem is the EF. Can be, can be not. There are a lots of points that we should take care, not only data access infrastructure.
With data access issued, as you are using only EF, you can gain fast improvement using simple .AsNoTracking()
method. Adopt a ServiceLocator to help you manage your contexts pool.
You can also user Dapper, instead of EF, in ReadOnly situations.
And for last, but not least, use pure ADO.NET, for the more complex queries and a fastest execution.
Refactor your ActionFilters to avoid using some "BaseController" that all controllers inherits is a good practice either.
Check if your IDisposable classes are truly being supressed by CG, adopting the .Dispose(bool)
pattern.
Be sure that you are not persisting cache variables for eternity, that will only be released by application pool recycle.
That are just tips, but the hard work will be with you, that have code access. :)
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With