GCLatencyMode.LowLatency是一个好的选择吗?

7
我有一个作为服务器的C# Windows服务,该服务在内存中保存一些大型(>8Gb)数据结构,并通过远程调用向客户端公开搜索方法。
平均搜索操作执行时间小于200毫秒,服务每秒处理多达20个请求。
我注意到定期出现严重的性能下降(> 6000毫秒),持续几秒钟。
我最好的猜测是服务器线程不时被gen2垃圾回收器停止。
我正在考虑从服务器GC切换到工作站GC,并将我的搜索方法包装在其中以防止请求期间发生GC。
 static protected void DoLowLatencyAction(Action action)
    {
        GCLatencyMode oldMode = GCSettings.LatencyMode;
        try
        {
            GCSettings.LatencyMode = GCLatencyMode.LowLatency;
            // perform time-sensitive actions here
            action();
        }
        finally
        {
            GCSettings.LatencyMode = oldMode;
        }
    }

这是一个好主意吗?

在低延迟块中,GC会在什么条件下执行?

注意:我正在一台带有8个核心的x64服务器上运行。

谢谢。


5
不要猜测问题的原因。使用性能分析器、性能计数器、记录日志等工具来找出实际的问题所在。 - StingyJack
4
是的,我使用了性能计数器和日志记录,发现是垃圾回收时间。 - Luca Martinetti
3个回答

10

我以前没有使用过GCLatencyMode,所以无法评论使用它是否是一个好主意。

然而,您确定您正在使用服务器GC吗?默认情况下,Windows服务使用工作站GC。

我以前在Windows服务中遇到过类似的问题,并使用以下命令设置了服务器GC模式:

<configuration>
    <runtime>
        <gcServer enabled="true" />
    </runtime>
</configuration>
在服务的app.config文件中解决了这个问题。 阅读Tess Ferrandez博客上的这篇文章以获取更详细的信息。

3
我很惊讶你的搜索方法甚至会触发GC,如果8GB数据结构是静态的(添加或删除不多),而你所做的只是搜索它,那么你应该尽量避免在搜索方法中分配临时对象(如果可能的话)。创建对象就是触发GC的事情,如果你有一个很少修改的数据结构,那么避免GC是有意义的(或者尽可能延迟它)。
GCSettings.LowLatency是给GC一个提示,使其急切地进行收集,以便在设置LowLatency模式时避免Gen2集合。这样做的副作用是使GC急于在设置LowLatency模式之外的区域进行收集,并可能导致性能降低(在这种情况下,可以尝试使用服务器GC模式)。

0

这听起来不是一个好主意。在某个时候,垃圾回收器将忽略您的提示并进行收集。

我相信通过实际分析和优化您的服务,您将获得更好的成功。在服务器运行时运行PerfView(免费,强大的Microsoft工具)。查看谁拥有麻烦对象以及特定长时间运行的GC事件需要多长时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接