Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excessively high memory usage in .NET MVC/Entity Framework application

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.

enter image description here

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:

  • Presentation - ASP.NET MVC 3
  • Business - Objects, ViewModels, Interfaces
  • Infrastructure - Entity Framework Model
  • Data Access - ADO.NET Direct Data Access

If anybody is able to provide any pointers, I'd be very grateful.

like image 488
Nick Avatar asked Aug 16 '13 00:08

Nick


1 Answers

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!

like image 200
Thiago Lunardi Avatar answered Sep 26 '22 01:09

Thiago Lunardi