抑制C#垃圾回收

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

  1. .NET是否在浪费时间检查所有这些数据以对其进行GC操作?
  2. Gen 2 GC多久出现一次(检查所有对象的那个)?
  3. 有没有办法降低它的频率或暂时抑制它的发生?
  4. 我确切地知道当我准备好收集大量内存时,有什么方法可以优化它吗? 我目前正在调用GC.Collect(); GC.WaitForPendingFinalizers(); 那时候。

更新:Perf计数器“GC中的%时间”显示平均值为10.6%。

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

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

仅优化需要优化的内容。

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

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

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

 GC.SuppressFinalize(*your object*) 

更多信息: 链接文字

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

GC中的%时间是自上一个GC循环以来执行垃圾收集(GC)所花费的时间百分比。 此计数器通常表示垃圾收集器代表应用程序收集和压缩内存所做的工作。 此计数器仅在每个GC结束时更新,计数器值反映最后观察到的值; 它不是一般的。

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

以下是各种GC性能计数器的良好讨论。 似乎10%是临界可行的。

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

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

我对我们犯错误有多容易感到震惊。 我放弃了许多function,开始轻松一些对象。 含义:

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

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

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

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

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

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

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

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

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

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