C# GC终结器队列中存在大量对象
我正在调查我们的服务器.NET应用程序内存占用的缓慢而稳定的增长。为了便于调查,我对6个模拟真实负载的客户端进行了压力测试,这些客户端反复重复相同的使用模式。 当我通宵运行时,我可以看到内存占用增加了大约几百MB。在分析和比较相隔12小时的服务器内存快照后,发现大部分差异是由于C# GC终结器队列中存在大量对象,c#,.net,garbage-collection,server,C#,.net,Garbage Collection,Server,我正在调查我们的服务器.NET应用程序内存占用的缓慢而稳定的增长。为了便于调查,我对6个模拟真实负载的客户端进行了压力测试,这些客户端反复重复相同的使用模式。 当我通宵运行时,我可以看到内存占用增加了大约几百MB。在分析和比较相隔12小时的服务器内存快照后,发现大部分差异是由于ReaderWriterLock实例在终结器队列中等待造成的。他们中有超过60万人 通过分析我的代码并查看GC根目录,可以发现所有的ReaderWriterLock活动实例都来自我们软件中的DataSet实例。因此,我尝试
ReaderWriterLock
实例在终结器队列中等待造成的。他们中有超过60万人
通过分析我的代码并查看GC根目录,可以发现所有的ReaderWriterLock
活动实例都来自我们软件中的DataSet
实例。因此,我尝试创建DataSet
实例,以尽可能地消除它。在清理了一些代码并缓存了一些DataSet
实例以避免不必要的分配之后,差异减少了约25%,但看起来它们的数量更多
我的问题是:
DataSet
实例调用dispose请注意,我使用的是“服务器”模式GC,因为我们的服务器在不同的线程上并行处理请求。虽然我还没有弄清楚为什么终结器队列中有这么多的
ReaderWriterLock
实例,但我确实找到了解决问题的方法,并将它们处理掉了
调用DataSet.Dispose没有帮助。因此,我已经开始重用现有的DataSet
实例,而不是继续创建新实例,因为“有人说DataSet.Clear
很慢”——从长远来看,这不是(如果有的话)。
这种方法完全消除了终结器队列实例的问题。虽然我还没有弄清楚为什么终结器队列中有这么多的
ReaderWriterLock
实例,但我确实找到了解决问题的方法并将其清除
调用DataSet.Dispose没有帮助。因此,我已经开始重用现有的DataSet
实例,而不是继续创建新实例,因为“有人说DataSet.Clear
很慢”——从长远来看,这不是(如果有的话)。
这种方法完全消除了终结器队列实例的问题。除非内存压力,否则GC不会收集,你是说这是内存泄漏吗,或者只是有很多对象等待完成,没有内存压力来释放它们?@RonBeyer查看GC中的“%of time in GC”计数器看起来GC收集了很多,基本上服务器花费了将近一半的时间做GC(值一直徘徊在0-50-100)。也许我有太多的分配,GC无法跟上?除非有内存压力,否则GC不会收集,你是说这是内存泄漏,还是有很多对象等待完成,没有内存压力来释放它们?@RonBeyer看着GC计数器中的“%of time in GC”看起来GC收集了很多,基本上,服务器花费几乎一半的时间进行GC(值保持在0-50-100之间)。也许我有太多的分配,而GC在跟上时遇到了问题?如果您没有使用派生类,那么在
数据集上调用Dispose()
所做的唯一事情就是将其自身从站点中删除。如果容器有站点,则引发Disposed
事件。如果您不使用派生类,则它甚至不会对其拥有的数据表调用Dispose()
(顺便说一句,DataTable
所做的就是从站点容器中删除并引发其Disposed
事件)
在数据集上
所做的是将其自身从站点中删除。容器
如果有站点,则引发已处置事件。它甚至不会对其拥有的数据表调用Dispose()
(顺便说一句,所有DataTable
所做的只是从站点容器中删除并引发其Disposed
事件)