一些事实:我们已经开发了wcf服务,作为客户端和数据库之间的一层。它是自托管的,并作为windows服务运行。
该服务保留了几个缓存,其中最大的内存约为1-2 2gb。总内存使用量通常在5-8 8gb左右。连接是双工的,使用tcp协议,使用protobuf-net进行串行化。我们的连接客户端数量通常在1000-1500之间。服务器是一个新型号的8核xeon,内存为64 is,只运行服务。
问题:在x个时间后,它已经到处都是,从一天到一周,服务变得非常慢。需要0.5秒的请求可能需要超过1分钟。此行为持续15-40分钟,或直到服务重新启动。
我们做了什么:我们已经检查了网络和服务器的网络连接,没有问题。在此期间,f.eks的CPU利用率略有上升。30%平均到40-50%平均。我们采用了内存转储,在代码中没有阻止用户的逻辑锁,也没有太多的活动。我们最新的线索是垃圾收集器。在perfmon中,我们可以看到"% time In gc“持续超过90% (90-97%),并且收集计数不断增加。GC0和GC1。我们怀疑也有一个阻塞的GC2在运行,但我们不得不重新启动服务,因为它正在生产中,所以在我们运行perfmon的5分钟窗口内,它不会计入。内存使用量为7,6 Gb。注意:未完成的呼叫数会增加,因此呼叫会到达那里,但服务不会处理它们。
我的问题是,垃圾收集器是否会处于运行并持续阻塞超过15分钟的状态?或者这个问题可能与其他问题有关?
我们的服务在工作站模式和延迟模式下运行GC :交互式我们现在已经将其更改为服务器和SustainedLowLatency,并希望这将有所帮助。如果是垃圾收集器,我们还能做什么?
编辑:很大的内存使用量是设计出来的,缓存中的数据很大,并且有更多的内存可用。
发布于 2015-03-04 16:55:28
过多的垃圾收集通常是由代码问题引起的。您要么在短时间内创建了太多的对象,要么继续分配内存而不释放它。
实际上,有一个extensive checklist available on MSDN可以帮助您诊断问题。
非常大的GC2意味着其中的对象在多次垃圾回收中幸存了下来,这意味着它们在内存中保存的时间更长。这可能是您问题的根本原因。也许有一种缓存机制可以使用一些调优/保留策略(删除长时间不使用的数据)。
发布于 2016-01-29 23:58:32
我也有类似的情况。使用protobuf和WCF进行客户端通信的服务中的大型数据库数据缓存。缓存不仅仅是供客户端使用的,业务层使用缓存来执行操作。服务的内存占用可以在2 GB到10 GB之间。在8小时不活动后,我释放了缓存的一部分。这台机器有8个虚拟核心和32 GB内存。我使用的是.Net 4.5.1。
只要我从数据库加载缓存,GC就会在一小时内消耗98%的CPU。有趣的是,在我们的两种情况下,都没有内存压力。
我认为GC之所以被执行,是因为GC尝试为所有线程保留可用内存的位置发生了变化。由于一个线程在加载缓存时分配了大量内存,因此GC开始工作。我不得不做几件事来修复它。
1)从缓存中删除元组。我将它们用作字典键,而它们的StructuralEquality实现非常糟糕。它将所有属性作为对象进行比较,因此对于值的属性会进行大量的装箱操作,并且在某些时候必须对这些属性进行垃圾回收。
2)当替换用作键的元组时,我不能简单地将它们替换为没有实现Equals的结构,因为值比较使用反射,而且它太昂贵了,所以我最终创建了一个通用的对结构。当对象在数组中时,我决定使用结构来删除它们的数量。
3)为了删除元组,我必须创建我自己的配对结构,它使用属性类型的默认equals来比较属性。本质上和PowerCollections创建的东西是一样的。
https://stackoverflow.com/questions/28850042
复制相似问题