在某些情况下防止GC集合以提高性能

时间:2015-07-22 10:26:51

标签: c# .net performance garbage-collection

我正在进行蒙特卡罗模拟。 工作在许多不同的机器之间进行分区(通常大约150个)。

每次迭代后,每个工作人员将其结果发送到服务器。 从所有工作人员获得结果后,服务器会计算更新并将其发送回所有工作人员。

此循环重复100-1000次迭代。

在所有工作人员发送结果之前,服务器无法计算更新,因此如果99名工作人员需要1秒钟完成迭代而第100名工作人员需要10秒钟,那么整个迭代需要10秒钟。

问题在于GC会在一些迭代中随机启动某些工作人员,因此会导致这些工作人员花费更多时间,从而减慢整个过程。

例如在迭代#1期间,#58工作者需要10秒钟,其他工作人员需要8秒钟。在迭代#2中,不同的工作者需要更长的时间,等等。

这增加的开销似乎在20-30%左右。

我想做的是指示GC在进行迭代时不要进行任何收集。 只收集每次说10次迭代(以便所有工作人员同步他们的集合),或者在发送结果后收集,并在从服务器获得更新之前收集。

这是我正在尝试做的伪代码:

public void Algorithm()
{
  for (var iteration = 0; iteration < 1000; iteration++)
  {
     PerformIteration(); //don't do any GC inside.
     SendResults();
     //Now there is a small time window to perform GC
     //before results from the server arrive (thats usually sub 0.5sec window)
     WaitForUpdate();
  }
}

设置:GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency帮助了很多,但仍然存在很大的开销。

每个工人有244克的压头,远远超过模拟要求。 此外,几乎所有内容都被缓存,因此无需进行Gen2集合。

2 个答案:

答案 0 :(得分:5)

.NET 4.6具有名为GC.TryStartNoGCRegion的新GC功能。

这告诉GC尝试运行这段代码而不进行任何收集:

  

尝试在执行期间禁止垃圾收集   如果指定数量的内存可用,则为关键路径   控制垃圾收集器是否完全阻塞垃圾   如果最初没有足够的内存,则收集。

当您调用它时,您可以指示GC在执行GC之前可以分配多少内存。它必须小于或等于短暂的段大小:

public void Algorithm()
{
   for (var iteration = 0; iteration < 1000; iteration++)
   {
        // allow the GC to allocate 4kb
        if (GC.TryStartNoGCRegion(4096, true))
        {
            try
            {
                PerformIteration();
                SendResults();
            }
            finally
            {
                GC.EndNoGCRegion();
            }
        }

      //Now there is a small time window to perform GC
      //before results from the server arrive (thats usually sub 0.5sec window)
      WaitForUpdate();
   }
}

答案 1 :(得分:0)

-您可以在{#3}}的C#上使用非托管代码

-或使用托管的 GC块

GC.TryStartNoGCRegion(.)
{
   // your critical code
} GC.EndNoGCRegion()

*不要忘记像以前的回答一样检查尝试条件

-this (GC.AddMemoryPressure)GCSettings.LatencyMode

使用MS manualgcServer参数在 *。config 文件(应用程序或计算机)中

更改GC配置

<configuration>
    <runtime>
        <gcServer enabled="true"/>
<!-- OR / AND -->
        <gcConcurrent enabled="true|false"/>
    </runtime>
</configuration>