【发布时间】:2013-12-11 11:33:27
【问题描述】:
我们有一个执行大量内存分配(短期和长期)的服务器应用。我们在启动后不久就看到了大量的 GC2 收集,但这些收集在一段时间后会平静下来(即使内存分配模式是恒定的)。 这些系列很早就达到了性能。
我猜这可能是由 GC 预算引起的(对于 Gen2?)。是否可以通过某种方式(直接或间接)设置此预算以使我的服务器在开始时表现更好?
我看到的一组违反直觉的结果:我们大幅减少了内存(和大对象堆)分配量,从长远来看性能有所提高,但早期性能变得更糟,并且“安定下来”的时间越来越长。
GC 显然需要一段时间才能意识到我们的应用程序是内存大户并相应地适应。这个事实我已经知道了,怎么说服GC呢?
编辑
- 操作系统:64 位 Windows Server 2008 R2
- 我们正在使用 .Net 4.0 ServerGC 批处理延迟。尝试了 4.5 和 3 种不同的延迟模式,虽然平均性能略有提高,但最坏情况下的性能实际上恶化了
编辑2
- GC 峰值可能会花费一倍的时间(我们所说的秒数)从可接受变为不可接受
- 几乎所有的峰值都与第 2 代集合相关
- 我的测试运行导致最终的堆大小为 32GB。最初的泡沫会持续 1/5 的运行时间,之后的性能实际上更好(不那么频繁的峰值),即使堆在增长。接近测试结束时的最后一个尖峰(具有最大的堆大小)与初始“训练”期间的 2 个尖峰的高度相同(即一样差)(堆小得多)
【问题讨论】:
-
你观察到的符合我的理解。当应用程序启动时,它正在经历一个恒定的增长期。每次应用程序达到(软)内存上限时,它都会运行一次 GC,以查看它是否可以在请求更多空间之前腾出空间。我还没有遇到任何让您在应用启动时保留大内存块的东西。
-
您能告诉我您使用的是哪个操作系统吗?我的意思是 32 位还是 64 位?
-
你不能,GC团队完全相信他们应该是配置收集器的人。而且您永远无法准确地提供可以调整算法以根据使用情况动态调整的配置。所以他们没有给我们选择,这就是它结束的地方。
-
也许你可以分配几百兆字节的
byte[1024],直到它们都被分配为止。然后你放下它们并开始正常启动。这可能会扩大 GC 预算。不过,我认为这是一个可怕的 hack。 -
尝试一个完全不同的解决方案:在后台启动您的应用程序的第二个副本,对其进行预热,然后使用 IIS 绑定自动将其与当前实时版本交换。这样一来,服务消费者就不会产生任何启动成本。
标签: c# .net memory-management garbage-collection