可以在.NET中抑制gen 2 GC收集吗?

可以在.NET中抑制gen 2 GC收集吗?,.net,garbage-collection,.net,Garbage Collection,我的程序分配了大量实例,这些实例构成了一个长寿命的DAWG。在构建这个DAWG的过程中,有时进度会减慢100倍,这与.NET执行gen 2 GC收集的情况完全相关。在这些时间段内,“%time in GC”为99.5%,并且“gen 2 collections总计”每隔几秒钟递增一次。经过几次背对背的gen 2收集后,它们会在没有明显原因的情况下停止触发,程序再次加速。几分钟后,循环重新开始 我创建的实例数量大约为2500万个,它们占用了几GB的RAM,因此gen 2集合占用这么长时间也就不足为

我的程序分配了大量实例,这些实例构成了一个长寿命的DAWG。在构建这个DAWG的过程中,有时进度会减慢100倍,这与.NET执行gen 2 GC收集的情况完全相关。在这些时间段内,“%time in GC”为99.5%,并且“gen 2 collections总计”每隔几秒钟递增一次。经过几次背对背的gen 2收集后,它们会在没有明显原因的情况下停止触发,程序再次加速。几分钟后,循环重新开始

我创建的实例数量大约为2500万个,它们占用了几GB的RAM,因此gen 2集合占用这么长时间也就不足为奇了。令人惊讶的是,gen 2系列以“火车”的形式出现,并且不断触发

我能在不彻底反思我的方法的情况下以某种方式防止这种情况发生吗?也许有什么办法可以要求.NET暂停第2代收集,直到另行通知?除了这些事件外,程序运行得非常高效,因此除了这种不幸的极端行为外,.NET显然能够胜任这项任务

(我尝试将GCSettings.LatencyMode设置为GCLatencyMode.Batch,但问题仍然存在。在GCs开始运行时,可用物理RAM的容量约为1GB。这是在64位计算机上。)

否。 您不能抑制它,因为它是保证程序正确性所必需的(至少就框架而言)

简单地说,CLR不会让你过这样危险的生活。如果您需要手动内存管理,那么您必须使用
struct
s创建自己的数据结构,并手动管理所有内容



也就是说,2500万是很多对象,但它不应该是几GB,除非您的对象也相对较大。可以使用结构数组而不是类来避免额外的引用吗?您可以删除任何信息吗?

在.NET 4.5+中,您可以使用新的
GCLatencyMode
选项指定您对较少的第2代集合的偏好

GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
更多信息请点击此处:

我的应用程序无法容忍在特定时间窗口内暂停

越来越多的.NET开发者开发了商业应用程序和 根据定义的业务提供结果的服务 需求或SLA。股票市场是必须提供服务的例子 在市场开放时提供非常及时的结果。通常,这些 应用程序在需要时执行重要的工作 提供低延迟结果。但他们不能容忍明显的错误 由于集合而暂停

我们的客户告诉我们,他们将在他们的服务器上部署更多内存 如果这样做,服务器将删除较长的暂停时间(通常为 由全封闭地面军事系统引入)。在.NETFramework4.5中,我们 通过引入SustainatedLowlatency模式提供了该选项 避免完全阻塞地面军事系统。此模式也适用于 通过更新4.0.3在.NET Framework 4中安装工作站GC

当SustainatedLowlatency设置生效时,第0代, 第1代和后台第2代集合仍然存在,并且 通常不会造成明显的暂停时间。阻塞第2代 只有当机器内存不足或应用程序 通过调用GC.Collect()来诱导GC。您的部署至关重要 将SustainedLowLatency设置用于具有 足够的内存,因此它们将满足堆中产生的增长 当设置生效时

在.NET Framework 4.5中,SustainatedLowlatency模式可用于 工作站和服务器GC。要打开它,请设置 GCSettings.LatencyMode属性转换为GCLatencyMode.SustainatedLowlatency。 NET Framework 4包括工作站GC的低端模式; 但是,此设置仅适用于短时间 时间,而SustainedLowLatency模式旨在用于 再长一点

还有一个
NoGCRegion
,你可以试试

指示应用程序运行时垃圾收集已挂起 执行关键路径。NoGCRegion是只读值;就是, 无法将NoGCRegion值分配给GCSettings.LatencyMode 财产。通过调用 TryStartNoGCRegion方法,并通过调用 EndNoGCRegion方法


我们在缓存社交+路由数据时也遇到了类似的问题。 由于网络流量(甚至在本地主机上)的原因,我们不得不缓存数亿个条目,因为在进程外存储这些条目的速度不够快。 相反,我们创建了一个特殊的100%托管内存管理器,它分配字节[]段,子内存管理器分配空间。CLR堆中的对象通过一个比BinaryFormatter快几个数量级的特殊二进制序列化转换为“PilePointers{int segment,int address}”。因此,现在,任何复杂度和大小的对象图都可以在托管堆中存储一段LOMG时间,而GC阻塞暂停<10 ms,完整GC大约为30-60 ms

我们在64Gb PC上轻松存储30000000个对象,其中最有趣的部分是:该解决方案比通过封送或通过redis/memcache将对象存储在未管理的堆中要快得多

见此: 桩:

缓存:

获取代码(Apache 2):

从.NET 4.6开始,您可以使用GC.TryStartNoGCRegion和GC.EndNoGCRegion方法在代码区域中“尝试禁止”垃圾收集

try
{
    GC.TryStartNoGCRegion(TOTAL_SIZE, true);

    <No GC region code here>
}   
finally
{
    if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) GC.EndNoGCRegion();
}
试试看
{
GC.TryStartNoGCRegion(总尺寸,真值);
}   
最后
{
if(GCSettings.LatencyMode==GCLatencyMode.NoGCRegion)GC.EndNoGCRegion();
}
有关参数和可能的异常的更多信息,请参阅

然而,仍然没有保证