Reputation: 3823
I was wondering what are the best practices when creating objects, performing LINQ in C#. For instance, I realize that when I open up a connection using LINQ I should be putting the model object into a using statement like this:
using(var ctx = new mymodel())
{
}
Now, what about the objects that are EF classes?
They do not implement IDisposable interface thus I can't do something like this when creating an object like this for example:
using(var user = new Users())
{
}
But when an action is called like this:
public ActionResult InsertUser()
{
var user = new Users();
}
I have no clear picture what happens with this object once the insert into the db is finished. Does this object stays allocated in memory or it gets released? If not, what are best practices to release memory once they aren't needed anymore..?
On the other there are static variables as well...
So to sum things up, my questions are:
what are best practices to release memory when creating instances of an object of a class?
Is implementation of IDisposable interface on every class that I have good choice?
When a static variable is created in .NET MVC, what is the best way to release memory taken by this kind of variables?
Same question goes for Session object?
P.S. Guys, I'd really appreciate if all of you that are reading this to post your opinion or post some useful links for some documentations/blog posts so that I can expand my horizons =)
Upvotes: 1
Views: 574
Reputation: 2868
In the case of var user = new Users();
which does not implement IDisposable, and any object for that matter which is not disposed, will only be guaranteed to exist where there is an active reference to this object; after which it will qualify for disposal the next time the Garbage Collector (GC) tries to free up memory.
In your example above, as soon as this leaves the method InsertUser()
it will no longer have any references pointing to it, and therefore will be up for garbage collection.
If however a reference exists, such as in the following code, the object will not be disposed until the reference is cleared, or the containing class is disposed.
private User _insertedUser;
public ActionResult InsertUser()
{
_insertedUser = new Users();
}
The garbage collector fires when the application needs to release some memory. When it fires, it performs several sweeps on objects within memory to tell if any references exist. It first scans every object which has been newly created since the last time the GC was called. Objects which survive this sweep are promoted a generation. If after the sweep more memory is still required, then a 2nd generation sweep is performed. This will scan every object which has survived a single garbage collection to see if it can now be freed. Again if an object survives, it moves up another generation, with 3 generation sweeps in total.
This method helps the GC perform memory management while limiting the high costs involved (newer objects are more likely to be available for release). As GC has a high cost associated to it, it's better if objects are disposed of through user's code to help limit the number of times the GC is called.
tldr;
Upvotes: 0
Reputation: 101453
In response to comment.
When you create regular .NET object, .NET runtime knows everything about it, because runtime created it. It knows where in memory it's located, when it is no longer needed and so on. When it is no longer needed - runtime will reclaim its memory. That is managed (by runtime) object. You should not care about memory management for such objects.
Now take for example file handle. When you open file in .NET, it will delegate this operation to OS (for example, Windows). This resource is not managed by runtime, it is managed by OS. So, it is unmanaged resource. So author of .NET library code which works with files (I mean person who created FileStream
and similar classes, not uses them) should manually write code to release such resource (close file handle in this case). By convention, author will use IDisposable.Dispose
method for code that releases such resources AND ensures that when underlying object (like FileStream
) will be collected by GC - unmanaged resources will also be released. So even if you forget to call Dispose
- file handle will be closed when GC collects FileStream
(not that it will happen not magically but because code author explicitly made it happen like this). But that might happen any time in the future, you don't want to leave file handle open for undetermined time - so you always call Dispose yourself when you are done with IDisposable
object.
The same applies to most unmanaged resources. For example, database connection is managed by database, and you don't want to leave database connection open for undetermined time, so you call Dispose
and explicitly notify database to close it (and even if you don't call it - author of .NET database code took care to do that when object is collected). EF context wraps database connection, so it also implements IDisposable
. If you don't want to leave connection open until context will be collected (and you sure don't want that) - you call Dispose
yourself.
Or suppose you write your own code to work with images using ImageMagick. That is C library, so runtime has no idea about its inner workings. You ask library to allocate memory for your image, but .NET cannot reclaim such memory - it does not manage it, it is managed by ImageMagick C library. So you implement IDisposable
and tell ImageMagick to release memory in that method.
Upvotes: 2
Reputation: 35106
Before you do any performance tweaks I highly recommend to run a memory profiler (for example JetBrains dotMemory, but there are others) and find out the actual source of the problem. Without information from profiler, your optimisations will be like sticking your finger at a sky and shouting "Rainbow!" i.e. useless at best, harmful at worst.
Also after identifying issues with profiler, but before starting changing your code, I recommend reading about how Garbage Collection works in .Net. Here are some references to get you started:
Here are some links to answer your questions:
Upvotes: 4