.Net内存管理问题:第2代中存在的对象

时间:2011-02-19 18:52:48

标签: c# .net performance memory-management

我已经使用VS2010探查器分析了我的应用程序,并启用了对象生命周期收集 我很惊讶地发现GC的大多数实例名为“Record”被收集为Gen 2实例。我非常沮丧,因为“记录”结构的实例每个应该少于500毫秒(理论上)。

这些结构是6xInt32左右的简单时间序列数据,它们在流上读取,在队列中排队/出队,大小为1000,传递给处理器,根据数百万“记录”触发某些逻辑顺序。我不需要一次保存超过50条记录。

所以我的问题是:为什么这些对象可以活得足够长,最终可以作为第二代引用,以及我可以做些什么来确保它们在每次计算后都被丢弃。

编辑: 我问这是因为我注意到更大样本量(即记录号)的性能急剧下降:如果N需要T分钟,2N需要2.5T分左右,依此类推。
所以显然有一个在某处泄漏。

编辑2: 我的错误:创建结构实例不会导致垃圾回收 我把它改成了课程,到目前为止没有发现任何重大改进。 我将再次运行探查器,这次没有结构化的类)并看看它给出了什么

编辑3: 许多答案怀疑Boxing / Unboxing发生在某个地方。 我使用类型化的通用集合和类型化的队列。并且“记录”从不作为成员附加到任何类。它们由事件单独处理。 ex-Struct(Now Class)实现了一个接口,并在被调用时由它进行转换(这是相当常见的用法)并且我放弃了该接口。没有改善。

编辑4: 我再次运行了探查器,逐个类替换struct。我有相同的结果:左 CLASS “记录”的大部分实例最终仍被收集为Gen2实例

编辑5: Record类的生产者有许多并行的 BackGroundWorkers (字节读者),并且有一个消费者线程在执行一些检查后将记录分派给其他方法。此外,我使用事件和代表在不同部分之间进行通信。我没有取消注册这些事件,因为它们在整个过程中都很有用(我可能在这一点上错了)

3 个答案:

答案 0 :(得分:1)

如果您将它们存储为局部变量(根据您的场景可能会或可能不会),它们将永远不会在堆上结束。

如果可以的话,我建议尝试一下。如果您发布代码示例,则可能会得到更深入的响应。

作为一个完整性检查,您是否忘记取消注册静态事件,或使用其他可能正在执行此操作的类(某些类通过Dispose修复此问题)?

您是否也考虑过使用Flyweight pattern

的可能性

编辑 - 由于您现在声称自己正在处理某些事件,因此极有可能导致您的问题。你忘记取消注册活动吗?

答案 1 :(得分:1)

如果您对内存使用“很重”,并且您使用的是C#4.0,则可以尝试“服务器”GC。将app.config(或web.config)与:

合并
<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

(使用merge我的意思是,如果你已经有了这些部分中的一部分,请使用它们,否则会创建它们。“configuration”是app.config的第一级元素)。这对某些应用程序(不需要与用户进行大量交互的应用程序)更好[/ p>]

答案 2 :(得分:0)

他们最终成为第二代,因为GC决定不垃圾收集它们。我不认为这是一个值得担心的问题。如果你真的想要,你可以重用1000个对象而不是不断创建新对象。这将使得这些对象不需要收集垃圾。您可以强制垃圾收集以确保对象“真正”被转储,但这会降低性能,因为GC是一项昂贵的操作,或者我被告知。