抑制C#垃圾回收

时间:2009-06-10 14:31:22

标签: c# garbage-collection

我的应用程序分配了大量内存(数百万个小对象,总计几千兆字节)并且长时间保留它。

  1. .NET是否浪费时间检查所有这些数据以对其进行GC?
  2. Gen 2 GC的发生频率(检查所有对象的那个)?
  3. 有没有办法降低它的频率或暂时抑制它的发生?
  4. 我确切地知道当我准备好收集大量内存时,有什么办法可以优化吗?我目前正在调用GC.Collect(); GC.WaitForPendingFinalizers();那个时候。
  5. 更新: Perf计数器“GC中的%时间”平均显示为10.6%。

6 个答案:

答案 0 :(得分:24)

除非您确认垃圾收集器正在积极降低应用程序的性能,否则您不应采取措施来削弱运行时环境的功能。

从您的问题判断,您尚未确认GC是个问题。我严重怀疑它是不是。

仅优化需要优化的内容。

答案 1 :(得分:9)

查看System.Runtime.GCSettings.LatencyMode属性。

在app.config中将GCServer属性设置为true也有助于减少GC(在我的情况下,启用时减少10倍的GC)。

答案 2 :(得分:9)

您可以使用静态方法阻止垃圾收集器完成任何对象:

GC.SuppressFinalize(*your object*)

此处提供更多信息:link text

答案 3 :(得分:7)

您可以使用性能监视器进行测量。打开perfmon并添加与.NET CLR Memory相关的性能计数器。这些计数器是特定于流程的,您可以使用它们跟踪各代的集合数量和大小,并且更加特别地为您指定“GC中的%时间”。以下是此计数器的说明文字:

  

%GC中的时间是百分比   花费的经过时间   执行垃圾收集(GC)   自上一次GC循环以来。这个柜台   通常是工作的一个指标   由垃圾收集器完成   代表申请收集   和紧凑的记忆。这个柜台是   仅在每个GC结束时更新   并且计数器值反映了   最后观察到的值;它不是   平均。

如果您在运行程序时观察这些计数器,则应该根据您的内存决定来回答GC的频率和成本。

Here是对各种GC性能计数器的良好讨论。似乎10%的边界是正常的。

答案 4 :(得分:3)

只有当GC需要一些gen2内存时才会(通常)发生(因为gen1已满)。你是在推测性地问这个问题,还是GC实际上有一个问题,因为你占用了大部分的执行时间?如果您没有问题,我建议您暂时不要担心 - 但请注意性能监视器。

答案 5 :(得分:1)

我的ASP.NET应用程序 - B2B系统 - 当第一个用户访问它时,用于启动35-40MB。在这么几分钟之后,应用程序过去常常增长到180 MB,有2或3个用户点击页面。 在阅读.net开发最佳实践和GC性能指南后,我发现问题是我的应用程序设计。我不同意。

我很害怕我们犯错误有多容易。我放弃了许多功能,并开始轻松一些对象。含义:

  1. 避免混合这么多页面以及智能和交流的用户控件(具有许多功能的控件,这些功能实际上对于使用此控件的每个页面最为存在)。

  2. 停止在基类上产生通用功能。有时候最好重复一次。继承是成本。

  3. 在一些复杂的功能上,我把所有东西放在同一个函数上。是的,最多达到100行。 当我在.net性能指导中阅读这篇建议时,我不相信它,但它有效。调用堆栈是一个问题,使用类属性超过局部变量是一个问题。班级变量可能是一个地狱......

  4. 停止使用复杂的基类,不应存在超过7行的基类。如果你在整个框架上传播更大的类,你就会遇到问题。

  5. 我开始使用更多静态对象和功能。我看到其他人设计的应用程序。所有dataaccess对象方法(插入,更新,删除,选择)都是静态的。具有更多并发用户的应用程序永远不会超过45MB。

  6. 为了保存一些项目,我喜欢改变状态模式。我在现实世界中学到了,但作者Nygard也在他的书上同意我的观点:发布IT - 设计和部署生产就绪软件。他把这种方法称为稳态模式。这种模式表明我们可能需要一些东西来释放闲置的资源。

  7. 您可能需要使用机器配置文件。在属性memoryLimit上,您将指示在进程回收之前可以达到的内存百分比。

  8. 您可能还想玩机器配置文件。在此属性上,GC将指示机器行为(Workstation GC和Server GC)。此选项也可能会显着改变内存消耗行为。

  9. 当我开始关心这些物品时,我取得了很大的成功。希望这有帮助。

    - 2014年5月4日编辑 由于GC新版本的改进以及HTML 5和MVC框架的进步,我已经改变了很多想法。