Advance Memory Management

 

Caching objects

 

Keep all the objects like view Model objects, Model objects, business objects, static objects etc.. in a centralized Cache. Disposing centralized cache can promote greater memory reductions.

Microsoft provides built-in Cache in .NET runtime, but I recommend strongly not to use it, because if there are exceptions cache is invalidated automatically. Beside it will be hard time to remove all the cache items during session timeout, applications sign-out, reloading new controls etc. The Cache has to be invalidated during all these times.

The custom light weight, application specific cache looks like below:

public class ApplicationCache

    {

        Dictionary<string, object> CentralCache = new Dictionary<string, object>();

 

        public void Add(string key, object Value)

        {

            if (!CentralCache.ContainsKey(key))

            {

                CentralCache.Add(key, Value);

            }

        }

 

        public object GetItem(string key)

        {

            if (CentralCache.ContainsKey(key))

            {

                return CentralCache[key];

            }

            return null;

        }

        static ApplicationCache cache = null;

        public static ApplicationCache CreateInstance()

        {

            if(cache == null)

            {

                return new ApplicationCache();

            }

            return cache;

        }

    }

 

In this, assigning null to cache will invalidate the whole cache, and programmer has more control on cache and will not be invalidated automatically during exceptions.

Use this Cache similar to WeakReference. Like keeping objects in weak reference, maintain the object in this cache, which provide more benefits,

Weak Reference

 

Avoid keeping objects in WeakReference as at any time the object may be removed by garbage collection and reference will be destroyed automatically.

Garbage Collection

 

It’s very important to understand, how garbage collection works, to build high performance, low memory intensive applications, which stands good after production.

All Managed objects in .NET will be held in Managed Heap, there will be no information on what the size of managed heap is or when the garbage collection is triggered.

It’s always good to trigger garbage collection at regular intervals or an actions like Changing the Navigation, application Sign-out, Session timeout etc.

Garbage collection happens on two types of objects:

  • Strong reference objects, by default all objects are of strong reference, the Garbage Collector requires the objects to be explicitly marked for collection.

ApplicationCache cache = new ApplicationCache();

  • object item = cache.GetItem("itemKey");

cache = null;

GC.Collect();

 

  • WeakReference objects, which are automatically picked up by the garbage collector. These objects need not to be marked explicitly and these are short lived objects.

class Program

    {

        static void Main(string[] args)

        {

           

            WeakReference refe = new WeakReference(new Test());           

            //test.Display("123");           

            GC.Collect();

            //test.Display("123");

            Console.WriteLine(refe.IsAlive);

            Console.Read();

 

        }

    }

    In the above code the refe.IsAlive print False, as object is wiped by Garbage collector.

One has to see proper trade-off between them before implementing solution.

Unmanaged objects:

 

The objects which performs the operation and doesn’t contains managed code, like FileStream objects, DataSet, DataTable, ComObjects, WCF service objects,  Channel objects, SQL connection objects, Command objects, windows GDI objects etc. requires manually Dispose those objects for memory cleanups.

It’s important to understand that these unmanaged objects consume large amount of memory and ignoring to dispose these objects can result in large memory leakage in the production, user can experience these while development also.

All the above mentioned objects, except ComObjects has Dipose() interface, which can be called after its use. The using block can be used and recommended for this kind of scenario. The following code demonstrates the same:

class Program

    {

        static void Main(string[] args)

        {

            DataSet ds = null;

            using (SqlConnection conn = new SqlConnection())

            {

                //Open the connection

                using (SqlCommand comm = new SqlCommand())

                {

                    //Command code here

                    //Excecute the command

                }

                ds.Dispose();

 

            }

 

        }

    }

  

In the above code all the unmanaged code like connection, command are embedded in using block and disposed automatically after going out of the scope.  The ds of type DataSet is disposed by calling dispose interface.

The com objects can be disposed as shown below:

while (Marshal.ReleaseComObject(comObject) > 0){}

The COM objects are wrapped inside Callable Wrapper. The Runtime Callable Wrapper has reference count every time COM interface pointed to it. The ReleaseComObject method decrements the reference count of runtime callable wrapper, if there are more than one reference then this method decrements and return the number of remaining references.

To ensure runtime callable wrapper and the original COM objects are released, the loop should be constructed until the return reference count is a zero.