Best practices to optimize memory in C#

You can use Redgate ANTS Memory profiler (non-free).

Or CLR profiler (free): https://msdn.microsoft.com/library/ms979205

GC.Collect() is not recommended even if it is required in some cases. Please have a look at below code:

private void WriteStringOnImage()
{
    try
    {
        byte[] imgData = getData(@"E:\0000.tif");
        using (System.Drawing.Image img = System.Drawing.Image.FromStream(new MemoryStream(imgData)))
        {
            for (int i = 1; i <= 1000; i++)
            {
                Bitmap img1 = new Bitmap(new Bitmap(img));
                RectangleF rectf = new RectangleF(800, 550, 200, 200);
                Graphics g = Graphics.FromImage(img1);
                g.DrawString(i.ToString("0000"), new Font("Thaoma", 30), Brushes.Black, rectf);
                img1.Save(@"E:\Img\" + i.ToString("0000") + ".tif");
                g.Flush();
                g.Dispose();
                img1.Dispose();
                GC.Collect();
            }
        }
    }
    catch (Exception){}
}

In the above example I used GC.Collect() because If I do not use GC.Collect() then it is taking memory around 1500mb. But after use of GC.Collect() if is never exceeding than 75mb

i.e. Memory utilization is decreased by 20 times.

But if GC.Collect() is being used excessively and there are not much unused objects lying in the memory then GC.Collect() will slow down your performance and it is time consuming.

You can also use Dispose() if it implements IDisposable.

If you are working with MemoryStream or any other type of stream, then you should use the using blocks.

Sometimes you also need to empty some object by making it null.

As we know data if we process XML data then it takes very heavy memory so we need to free the memory after use but XML class doesn't implement Idisposable interface so you have to make it null (e.g. xmldocument=null;)

You should also keep in mind about unnecessary object initialization.

e.g. Instead of:

ClassA abc=new ClassA();
abc=xyz;

Use:

ClassA abc=xyz;

Try to use method level variable instead of class level if it is being used in only one method.

Make sure you are clearing collection objects.

Keep watch on the memory usage by any third party tool which is being used in your application. Sometimes third party tools takes very high memory.

Use static only if it is must.

Use StringBuilder instead of String. Because if string is concatenated then a new memory is allocated so the old memory data is not being used but it is kept in RAM.

If any large object is being processed in hierarchical classes keep watch on it.

If any XML document is processed and has been kept in memory for future use and that will be use after any event then release that memory and load XML when the required event is fired.

Avoid cloning.

If You are working with string manipulation you can check the data for infinite loop. Sometime special Unicode characters like ellipsis(...) can create problem and causes for infinite loop.

You can also use dotTrace a memory profiler by Jetbrain.

You can also look into event log for any exception which is causing the issue.

If any bitmap object is being created and some image processing is being done then have a look on unmanaged Resources. A bitmap object take a huge memory for unmanaged resources and that might not be released.

As you have mentioned that you are also using SQL server then also keep watch on SQL server procedures and functions and their calling strategies.

In SQL Server if you are saving any data as image data type and if it is larger than 1mb then please use varbinary(MAX) with filestream property but it will work with SQL server 2008 or upper versions of SQL server.


Many of these don't really optimize memory...

  1. Dispose an object after use or make it null. Always Dispose() an object if it is IDisposable. This COULD save you memory problems, but not necessarily. (Also, use Using if possible)
  2. Use try/finally or using block. try/finally - This is similar to Using for objects that aren't IDisposable (I find them to be messy, so I prefer this solution.)
  3. Use GC.Collect() if required. I wouldn't really be able to ever recommend GC.Collect(). Normally the GC will do a better job on knowing when to collect something than you will.
  4. Remove unnecessary object initialization. This one can definately help. If your code is going around creating objects that aren't needed... then this could waste some space. This can be sorta allievated/masked with Lazy Initialization.
  5. Manage Image caching. This is VERY vague... but yes... its important to manage how many images you have stored in memory. It may not always be desirable to keep images in memory... It can open the door to paging for other processes in your code that are more critical.
  6. Manage BLOB data, Memory stream and file stream I think this is similar to #5.

best practices to optimize memory in C#,

  1. Create only the objects as and when needed
  2. Decide the scope for each variable and object, if they are required inside methods declare them inside those methods, do not make them private
  3. Use the IDisposable interfaces on your custom objects and release all the resources(if any), un-register from all the events etc
  4. Call dispose when an object is no long required for your custom objects
  5. Use least static variables or instances, if required then too think twice whether those objects are required in entire lifetime of program
  6. Do not use GC.Collect() manually,(it is bad practice)