Управление памятью для каждого потока в C#

Продолжаем обсуждение из раздела Понимание результатов параллельного профилирования VS2010 C#, но ближе к делу:

У меня есть много потоков, которые работают параллельно (используя Parallel.For/Each), которые используют много выделения памяти для небольших классов.

Это создает конфликт в потоке распределителя глобальной памяти.

Есть ли способ дать указание.NET предварительно выделить пул памяти для каждого потока и выполнить все выделения из этого пула?

В настоящее время моим решением является моя собственная реализация пулов памяти (глобально распределенных массивов объекта типа T, которые перерабатываются между потоками), что очень помогает, но неэффективно, потому что:

  1. Я не могу дать указание.NET выделить из определенного фрагмента памяти.
  2. Мне все еще нужно вызывать новый много раз, чтобы выделить память для пулов.

Спасибо,
Аггей

3 ответа

Решение

Я искал два дня, пытаясь найти ответ на ту же проблему, что и у вас. Ответ: вам нужно установить режим сбора мусора в режим сервера. По умолчанию режим сбора мусора установлен в режим рабочей станции. При установке сборки мусора в режим сервера управляемая куча разделяется на отдельные управляемые разделы, по одному на процессор. Для этого вам нужно добавить параметр конфигурации в ваш файл app.config.

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

Разница в скорости на моем 12-ядерном Opteron 6172 была впечатляющей!

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

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

Сборщик мусора не выделяет память.

Это больше похоже на то, что вы выделяете много маленьких временных объектов и несколько долгоживущих объектов, а сборщик мусора тратит много времени на сбор мусора временных объектов, поэтому вашему приложению не нужно запрашивать больше памяти у ОПЕРАЦИОННЫЕ СИСТЕМЫ. Из .NET Framework 4 Advanced Development - Сборка мусора:

Пока в управляемой куче доступно адресное пространство, среда выполнения продолжает выделять пространство для новых объектов. Однако память не бесконечна. В конце концов сборщик мусора должен выполнить сборку, чтобы освободить часть памяти.

Решение: не выделяйте много маленьких временных объектов. Также может быть полезна страница " Сборка мусора и производительность".

Другие вопросы по тегам