C # Heap (ing) Vs Stack (ing) in. Net:part IV

Source: Internet
Author: User
Tags garbage collection static class

Even though with the. NET Framework we don ' t have to actively worry about memory management and garbage collection (GC), W E still have to keep memory management and GC in mind in order to optimize the performance of our applications. Also, has a basic understanding of how memory management works would help explain the behavior of the variables we work  With in every program we write. In this article we'll look into the garbage Collection (GC) and some ways to keep my applications running efficiently by usin G Static class members.

smaller Feet = = more efficient allocation.

To get a better understanding of why a smaller footprint'll be more efficient would require us to delve a bit deeper into The anatomy of. NET memory allocation and garbage Collection (GC).

Graphing

Let's look in this from the GC's point of view. if we are responsible for "taking out the trash" we need a Do this effectively. obviously, we need to determine what are garbage and what are not (this might be a bit painful fo R the Pack-rats out there) . 

In order to determine what needs to be kept, we'll ' ll ' the assumption that's everything not being used is trash (t Hose piles of the papers in the corner, the box of junk in the attic, everything in the closets, etc.   Imagine We live with our two good friends:joseph Ivan Thomas (JIT) and Cindy Lorraine Richmond (CLR).  joe and Cindy keep track of what they are using and give us a list of things they need to keep. we ' ll call the initial list Our "root" list because we are using it as a starting point.  we'll be keeping a master list to graph where Everythin G is in "house" we want to keep. anything this is needed to make things on our list work'll be added to the Graph (if we ' re keeping the "TV we don ' t throw out the" remote control for the "TV, so it'll be added to the list. if We ' re keeping the computer the keyboard and monitor'll be added to the ' Keep ' list.

This is how the GC determines what to keep as. It receives a list of "root" object references to keep from Just-in-time (JIT) compiler and common language (CLR) (Remember Joe and Claire?) And then recursively searches object references to build a graph of what is should.

Roots consist of:global/static pointers. One way to make sure we objects are not garbage collected by keeping a reference to them in a static variable. pointers on the stack. We don ' t want to throw away what our application ' s threads still need into order to execute. CPU Register pointers. Anything in the managed heap of that are pointed to through a memory address in the CPU should be preserved (don ' t throw it out).

In the above diagram, objects 1, 3, and 5 in my managed heap are referenced from a root 1 and 5 are directly referenced a  nd 3 is found during the recursive search. If we go back to our analogy and object 1 are our television, Object 3 could are our remote control. After all objects are graphed we are ready "to" the next step, compacting.

Compacting

Now, we have graphed what objects we'll keep, we can just move the "keeper objects" around to pack things up.

Fortunately, in our house we don ' t need to clean out the spaces before we put something else there. Since Object 2 is not needed, as the GC we'll move Object 3 down and fix the pointer in object 1.

Next, as the GC, we ll copy Object 5 down

Now, everything is cleaned up we just need to write a sticky note and put it on the top of my we compacted heap to let C Laire know where to put the new objects.

Knowing the nitty-gritty of CG helps in understanding that moving objects around can be very taxing. As you can, it makes sense so if we can reduce the size of what we have to move, we ' ll improve the whole GC process Because there is less to copy.

What about things outside the managed heap?

As the person responsible for garbage collection, one problem we run into cleaning house are how to handle objects in th E car. When cleaning, we need to clean everything up. What if the laptop is in the "house" and "batteries are in the" Car?

There are situations where the GC needs to execute code to clean up non-managed resources such as files, database Connecti ONS, network connections, etc. One possible way to handle this is through a finalizer.

Class Sample

{

~sample ()

{

Finalizer:clean up here

}

}

Object 2 is treated in the usual fashion. However, when we are to Object 4, the GC sees that it is on the finalization queue and instead of reclaiming the memory ob Ject 4 owns, Object 4 is moved and it's finalizer is added to a special queue named Freachable.

There is a dedicated thread for executing freachable queue items. Once The finalizer is executed to this thread in Object 4, it is removed from the freachable queue. Then and only Then are Objet 4 ready for collection.

So Object 4 lives on until the next round of GC.

Because adding a finalizer to We classes creates additional work for GC it can be very expensive and adversely affect the Performance garbage collection and thus our program. Only use finalizers when you are absolutely sure you need them.

A better practice is to the sure to clean up non-managed resources. As you can imagine, it's preferable to explicitly close connections and use the IDisposable interface for cleaning up ins Tead of a finalizer where possible.

idisposaible

Classes that implement IDisposable perform clean-up in the Dispose () method (which was the only signature of the interface) . So if we have a Resouceuser class instead of using a finalizer as follows:

public class Resourceuser

{

~resourceuser ()//This is A FINALIZER

{

Do CLEANUP here

}

}

public class Resourceuser:idisposable

{

#region IDisposable Members

public void Dispose ()

{

Clean up here!!!

}

#endregion

}

public static void DoSomething ()

{

Resourceuser rec = new Resourceuser ();

Using (REC)

{

Do something

}//DISPOSE called here

DON ' T ACCESS rec here

}

public static void DoSomething ()

{

using (Resourceuser rec = new Resourceuser ())

{

Do something

}//DISPOSE called here

}

Static Methods

The Static methods belong to the type is not the instance of our object. This enables us to create items which are shared by all we classes and "trim the fat" so to speak.  Only pointers to We static method have to is moved around in memory (8 bytes). The static method itself'll is loaded once, very early in the application lifecycle, instead of being instance of our class. Of course, the bigger the more efficiency we gain by making it static. If Our methods are small (under 8 bytes) We'll actually get worse performance out of making it static because the Pointe R would be larger than it points to.

Here ' s the details ...

Let ' s say we have a class with a public method SayHello ();

Class Dude

{

private string _name = "Don";

public void SayHello ()

{

Console.WriteLine (this._name + "says Hello");

}

}

A (possibly) more efficient way be to make the method static so we only have one ' SayHello () ' in memory no matter Many dudes are around. Because static members are not instance members we can ' t use a reference to "this" and have to pass variables into the Met Hod to accomplish the same result.

Class Dude

{

private string _name = "Don";

public static void SayHello (string pname)

{

Console.WriteLine (pname + "says Hello");

}

}

Keep in mind what happens on the stack while we pass variables (the "this series"). We have to decide on a case-by-case basis whether using a-static method gives us improved performance. For instance, if a static method requires too many parameters and does no have very much internal logic (a small Footprin T), it is entirely possible we would loose the more efficiency-a static method of that we calling would.

Static Variables:watch out!

There are a couple of things we want to watch out for with static variables. If we have a class with a is static method, we want to return a unique number, the following implementation would be buggy :

Class Counter

{

private static int s_number = 0;

public static int Getnextnumber ()

{

int newnumber = S_number;

Do SOME STUFF

S_number = Newnumber + 1;

return newnumber;

}

}

We need to explicitly lock the Read/write memory operations to static variables in the can execute them. Thread management is a very large topic and there are many the to ways thread approach. Using the lock () keyword is one way to ensure only one thread can access a blocks of code at a time. As a best practice, you are should lock as little code as possible because threads have to wait in a \ Execute the code In the lock () blocks and it can be inefficient.

Class Counter

{

private static int s_number = 0;

public static int Getnextnumber ()

{

&nbs

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.