Best practices to optimize memory in C# [closed]

大城市里の小女人 提交于 2019-12-20 10:42:12

问题


What are the best practices to optimize memory in C#.

I am using following technique to optimize my memory.

  1. Dispose an object after use or make it null.
  2. Use try/finally or using block.
  3. Use GC.Collect() if required.
  4. Remove unnecessary object initialization.
  5. Manage Image caching.
  6. Mange BLOB data, Memory stream and file stream

Even if there is memory leakage.

My application is using following things:

  1. Processing configuration files,
  2. Using other XML files.
  3. Using image functions zoom-in, zoom-out, display different type of images, changing color of images, saving data in xml.
  4. Saving data in SQL server.

回答1:


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.




回答2:


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.



回答3:


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)



回答4:


..or make it null does not have the same effect than Dispose()! Be careful. You only should dispose your object. Set to null is not required And set to null does not immediate free any resources.

  1. Use GC.Collect() if required.

Normally this is not required, because the GC has his own lifecycle when to collect. Since .NET 4.5 you can compact the LOH, if you think there is a fragmentation:

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();    


来源:https://stackoverflow.com/questions/21046409/best-practices-to-optimize-memory-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!