User987
User987

Reputation: 3823

Minimizing usage of RAM by created objects in runtime in C#

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:

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

Answers (3)

Radderz
Radderz

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;

  • Dispose objects if they implement IDisposable; an easy way is to surround it by a 'using'.
  • If an object cannot be disposed, and it is no longer required, make sure all references to the object is cleared (especially references outside of a method which the object was created). This enables the GC to release it from memory.

Upvotes: 0

Evk
Evk

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

trailmax
trailmax

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:

  1. MSDN Garbage Collection
  2. MSDN Garbage Collector Basics and Performance Hints
  3. .Net Garbage Collection in depth

Here are some links to answer your questions:

Upvotes: 4

Related Questions