Предотвратите сборку мусора .NET за короткий промежуток времени

У меня есть высокопроизводительное приложение, которое обрабатывает очень большой объем данных. Он получает, анализирует и отбрасывает огромное количество информации за очень короткие промежутки времени. Это вызывает значительное количество оттока объектов, которые я в настоящее время пытаюсь оптимизировать, но также вызывает вторичную проблему. Когда сборка мусора в ней может вызвать некоторые длительные задержки, так как она очищает вещи (длинным я имею в виду от 10 до 100 миллисекунд). В 99% случаев это приемлемо, но для кратких окон времени около 1-2 минут я должен быть абсолютно уверен, что сбор мусора не вызывает задержки. Я знаю, когда эти периоды времени будут происходить заранее, и мне просто нужен способ убедиться, что сбор мусора не произойдет в течение этого периода. Приложение написано на С# с использованием .NET 4.0 Framework и использует как управляемый, так и неуправляемый код, если это имеет значение.

Мои вопросы:

  • Можно ли кратко приостановить сбор мусора для всей программы?
  • Можно ли использовать System.GC.Collect() для принудительного сбора мусора перед окном, в котором я нуждаюсь, без сбора мусора, и если я сделаю, как долго я буду свободным от мусора?
  • Какой совет у людей есть для минимизации потребности в сборке мусора в целом?

Примечание. Эта система довольно сложна с множеством различных компонентов. Я надеюсь избежать подхода, когда я должен реализовать пользовательский интерфейс IDisposable для каждого класса программы.

Ответ 2

GCLatencyMode oldMode = GCSettings.LatencyMode;

// Make sure we can always go to the catch block, 
// so we can set the latency mode back to `oldMode`
RuntimeHelpers.PrepareConstrainedRegions();

try
{
    GCSettings.LatencyMode = GCLatencyMode.LowLatency;

    // Generation 2 garbage collection is now
    // deferred, except in extremely low-memory situations
}
finally
{
    // ALWAYS set the latency mode back
    GCSettings.LatencyMode = oldMode;
}

Это позволит вам отключить GC столько, сколько сможете. Он не будет делать больших коллекций объектов, пока:

  • Вы вызываете GC.Collect()
  • Вы устанавливаете GCSettings.LatencyMode в нечто иное, чем LowLatency
  • ОС отправляет сигнал с низкой памятью на CLR

Будьте осторожны при выполнении этого, так как использование памяти может занять очень быстро, пока вы находитесь в этом блоке try. Если GC собирает, он делает это по какой-то причине, и вам следует только серьезно подумать об этом, если у вас большой объем памяти в вашей системе.

В отношении третьего вопроса, возможно, вы можете попробовать повторное использование таких объектов, как массивы байтов, если вы получаете информацию через вводы/выходы файловой системы или сеть? Если вы анализируете эту информацию в пользовательских классах, попробуйте повторно использовать их тоже, но я не могу дать слишком много хороших советов, не зная больше о том, что именно вы делаете.

Вот некоторые статьи MSDN, которые тоже могут помочь:

Примечание: GCSettings.LatencyMode = GCLatencyMode.LowLatency можно установить, если GCSettings.IsServerGC == false. IsServerGC можно изменить в App.config:

  <runtime>
    <gcServer enabled="false" />
  </runtime>