在C#中优化内存的最佳实践
在C#中优化内存的最佳实践是什么?
我正在使用以下技术来优化我的记忆力。
- 使用后处理对象或使其为空。
- 使用try / finally或使用块。
- 如果需要,请使用GC.Collect()。
- 删除不必要的对象初始
- 管理图像缓存。
- Mange BLOB数据,内存流和文件流
即使有内存泄漏。
我的应用程序使用以下内容:
- 处理配置文件,
- 使用其他XML文件。
- 使用图像function放大,缩小,显示不同类型的图像,更改图像颜色,以xml格式保存数据。
- 在SQL Server中保存数据。
您可以使用Redgate ANTS Memory Profiler (非免费)。
或CLR分析器 (免费): https : //msdn.microsoft.com/library/ms979205
即使在某些情况下需要GC.Collect()
,也不建议使用GC.Collect()
。 请看下面的代码:
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){} }
在上面的例子中,我使用了GC.Collect()
因为如果我不使用GC.Collect()
那么它的内存大约为1500mb 。 但使用GC.Collect()
如果永远不超过75mb
即内存利用率降低20倍 。
但是如果过度使用GC.Collect()
并且内存中没有太多未使用的对象,则GC.Collect()
会降低性能并且耗时。
如果它实现了IDisposable
您也可以使用Dispose()
。
如果您正在使用MemoryStream
或任何其他类型的流,那么您应该使用using
块。
有时您还需要通过使其为空来清空某个对象 。
因为我们知道数据如果我们处理XML数据然后它需要非常大的内存所以我们需要在使用后释放内存但XML类不实现Idisposable接口所以你必须使它为null(例如xmldocument=null;
)
您还应该记住不必要的对象初始化 。
例如,而不是:
ClassA abc=new ClassA(); abc=xyz;
使用:
ClassA abc=xyz;
如果仅在一个方法中使用方法级别变量而不是类级别,请尝试使用它。
确保清除收集对象。
通过应用程序中使用的任何第三方工具监视内存使用情况。 有时第三方工具占用非常高的内存。
仅在必须时使用static
。
使用StringBuilder
而不是String
。 因为如果连接字符串然后分配新的内存,那么旧的内存数据不会被使用,但它会保存在RAM中。
如果在分层类中处理任何大对象,请密切关注它。
如果处理了任何XML文档并将其保留在内存中以供将来使用,并且将在任何事件之后使用,那么在触发所需事件时释放该内存并加载XML。
避免克隆。
如果您正在使用字符串操作,则可以检查数据是否为无限循环。 有时像Unicode(...)这样的特殊Unicode字符可能会产生问题并导致无限循环。
你也可以使用dotTrace作为Jetbrain的内存分析器。
您还可以查看事件日志中是否存在导致问题的任何exception。
如果正在创建任何位图对象并且正在进行一些图像处理,那么请查看非托管资源。 位图对象为非托管资源占用大量内存,并且可能无法释放。
正如您所提到的,您还使用SQL服务器,然后还要关注SQL服务器过程和函数及其调用策略。
在SQL Server中,如果要将任何数据保存为图像数据类型,并且如果它大于1mb,那么请使用varbinary(MAX)和filestream属性,但它可以与SQL Server 2008或SQL Server的高级版本一起使用。
在C#中优化内存的最佳实践,
- 在需要时仅创建对象
- 确定每个变量和对象的范围,如果在方法中需要它们,则在这些方法中声明它们,不要将它们
private
- 使用自定义对象上的
IDisposable
接口并释放所有资源(如果有),取消注册所有事件等 - 当自定义对象不再需要对象时调用
dispose
- 如果需要,请使用最少的
static
变量或实例,然后再考虑在程序的整个生命周期中是否需要这些对象 - 不要手动使用
GC.Collect()
(这是不好的做法)
其中许多并没有真正优化内存……
- 使用后处理对象或使其为空。 如果对象是
IDisposable
始终Dispose()
。 这可以节省你的记忆问题,但不一定。 (另外,如果可能,请使用) - 使用try / finally或使用块。
try/finally
– 这类似于Using
非IDisposable
对象(我觉得它们很乱,所以我更喜欢这个解决方案。) - 如果需要,请使用GC.Collect()。 我真的不能推荐
GC.Collect()
。 通常情况下,GC
会更好地知道何时收集的东西比你想要的更多。 - 删除不必要的对象初始 这个可以肯定有帮助。 如果您的代码正在创建不需要的对象……那么这可能会浪费一些空间。 这可以通过延迟初始化进行分类/屏蔽。
- 管理图像缓存。 这非常模糊……但是是……管理你在内存中存储的图像数量非常重要。 将图像保存在内存中可能并不总是令人满意的……它可以为您的代码中更重要的其他进程分页打开大门。
- 管理BLOB数据,内存流和文件流我认为这类似于#5。
..or make it null
与Dispose()
没有相同的效果! 小心点。 你应该只处理你的对象。 不需要设置为null
。 并设置为null
不释放任何资源。
3.如果需要,使用GC.Collect()。
通常这不是必需的,因为GC有自己的生命周期何时收集..自.NET 4.5以来你可以压缩LOH,如果你认为存在碎片:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect();