为什么如果我不进行垃圾回收,服务器的垃圾回收速度会更快?

4
我正在编写一种数据结构,如果我在我的app.config文件中设置<gcServer enabled="true" />,则程序可以在 200 毫秒内添加500,000个项目。如果我设置<gcServer enabled="false" />,则需要300毫秒。也就是说,将此标志设置为false会使其始终需要更长的时间50%,使用Stopwatch测量。

我想知道为什么会这样,因为我没有执行任何垃圾收集。我知道有时是自动完成的,但在使用CLRProfiler进行分析后,我可以确认未发生0次垃圾收集:

enter image description here

是否有人知道原因?如果垃圾收集器甚至都没有运行,那么服务器垃圾收集器为什么要快得多?下面是我检查速度差异的代码:

Stopwatch sw = Stopwatch.StartNew();

foreach (string s in items)
{
    dataStructure.Add(s, s + "a");
}

sw.Stop();

仅仅因为你没有收集任何对象,不意味着垃圾回收算法没有运行并尝试在图形中查找可以收集的对象。也许这篇论文会阐明一些差异;https://msdn.microsoft.com/en-us/library/ee787088(v=vs.110).aspx - Erti-Chris Eelmaa
为什么在启动秒表之前执行 GCSettings.LatencyMode = GCLatencyMode.LowLatency; 会花费 600 毫秒的时间呢? - Ryan Peschel
请问一下,您是在无调试器附加的情况下以发布模式运行吗?(Ctrl+F5) - Erti-Chris Eelmaa
是的,在发布模式下我每次都确定要执行 Ctrl+F5。 - Ryan Peschel
1个回答

0
这里有五件事情需要讲述。
第一,了解这个标志并不是打开或关闭垃圾收集器,而仅仅确定使用的模式。两个例子都启用了垃圾收集;只有第一个(较慢的)例子使用了服务器垃圾收集。
第二,要明白,即使没有执行任何收集,也不意味着 GC 没有停止检查是否需要运行收集。
第三是 gcServer 文档摘录

对于单处理器计算机,默认的工作站垃圾回收应该是最快的选项。

第四,要理解上下文中的“单处理器”确实是指处理器,而不是核心。
把所有这些放在一起,问题的行为与文档完全匹配。继续前进;这里没有什么好看的。
第五点,也是最后一点,是理解在服务器上的价值观以及服务器负载与桌面负载的不同之处。服务器系统中的主要重点是 稳定性。即使是在性能方面,如果系统总是崩溃,性能也就无所谓了。此外,服务器更有可能运行工作负载,其中一个进程的寿命很长……甚至可能长达几个月或几年而无需重新启动。因此,服务器管理员可能会牺牲一些性能来获得运行频率稍高且运行更完整检查的 GC,这可能包括内存压缩以回收地址空间,并避免在长时间运行的 .Net 应用程序中可能导致问题的 OutOfMemoryExceptions。

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