.NET Garbagecollector麻烦。阻挡15-40分钟

时间:2015-03-04 08:48:59

标签: c# .net wcf garbage-collection

一些事实: 我们开发了wcf服务,充当客户端和数据库之间的层。 它是自动主存并作为Windows服务运行。

该服务保留了几个缓存,其中最大的内存大约为1-2gb。总内存使用量通常约为5-8gb。 连接是双工的,使用tcp协议,序列化使用protobuf-net。我们的连接客户端数量通常在1000-1500之间。 该服务器是一个8核xeon的新型号,内存为64GB,并且只运行该服务。

问题:经过一段时间后,从一天到一周的服务变得非常缓慢。需要0.5秒的请求可能需要一分钟。此行为持续15-40分钟或直到服务重新启动。

我们做了什么: 我们检查了服务器的网络和网络连接,没有问题。从f.eks开始,这段时间CPU利用率有所上升。平均30%至40-50%。 我们已经进行了内存转储,代码中没有逻辑锁来阻止用户,也没有多少活动。 我们最新的领导是垃圾收集器。在perfmon中,我们可以看到“gc中的%时间”不断超过90%,(90-97%)并且收集计数增加。 GC0和GC1都有。我们怀疑有一个阻止GC2运行,但我们不得不重新启动服务,因为它正在生产中,所以它在我们运行perfmon的5分钟窗口期间没有计数。内存使用量为7,6 Gb。 注意:未完成的呼叫会上升,因此呼叫到达那里但服务无法处理它们。

我的问题是,垃圾收集器是否可以进入运行状态并持续阻塞超过15分钟?或者问题可能与其他问题有关?

我们的服务在工作站模式和延迟模式下运行GC:交互式 我们现在已将其更改为Server和SustainedLowLatency,并希望这会有所帮助。如果它是垃圾收集器,还有什么我们可以做的吗?

编辑:大量内存使用是按设计进行的,缓存中的数据很大,并且有更多可用内存。

2 个答案:

答案 0 :(得分:4)

过多的垃圾收集通常是由代码问题引起的。您要么在短时间内创建太多对象,要么继续分配内存而不释放它。

实际上有一个extensive checklist available on MSDN可以帮助您诊断问题。

非常大的GC2意味着其中的对象幸存了多个垃圾收集,这意味着它们在内存中保留了更长的时间。这可能是您问题的根本原因。也许有一种缓存机制可以使用一些调优/保留策略(删除长时间未使用的数据)。

答案 1 :(得分:1)

我有类似的情况。使用带有WCF的protobuf进行客户端通信的服务中的大型数据库数据缓存。缓存不仅仅适用于客户端,业务层使用缓存来执行操作。服务的内存占用量可以在2到10 GB之间。我在8小时不活动后释放一段缓存。该机器有8个虚拟内核和32 GB内存。我正在使用.Net 4.5.1。

一旦从数据库加载缓存,GC就会消耗98%的CPU一小时。在我们的两个案例中,有趣的一点是没有记忆压力。

我认为执行GC无论是因为GC尝试为所有线程保留可用内存而改变了某些内容。由于一个线程在加载缓存时分配了大量内存,因此GC启动了。我必须做几件事来解决它。

1)从缓存中删除了元组。我使用它们作为字典键,它们对StructuralEquality的实现非常糟糕。它将所有属性作为对象进行比较,因此对于属性值进行大量装箱,这些属性必须在某些时候进行垃圾收集。

2)当替换用作键的元组时,我不能简单地用结构替换它们而不实现Equals,因为值比较使用反射并且它太昂贵所以我最终创建了一个通用对结构。我决定使用结构来删除数组中的对象数量。

3)要删除元组,我必须创建自己的Pair结构,使用默认的equals属性来比较属性。与PowerCollections创建的功能完全相同。