У нас есть ситуация, где мы рассматриваем принуждение сборки "мусора" на сервере, который является очень низким на RAM (3.6/4GB используемый в среднем). Нет, это не действительно опция обновить этот сервер, к сожалению.
Один из наших сервисных процессов (записанный косвенно в C++ (не спрашивают...)) действительно работает с компонентами.NET и затем спит в течение 10 минут. Когда тот сервис спит, он часто держится за 600 МБ RAM, которая могла быть совместно использована с другими процессами. Кажется так или иначе связанным с WSE, прослеживающим включаемый для отладки. Я могу смотреть, это проснуться и GC на следующем повторении на первом COM звонит в.NET - однако затем, процесс делает некоторую работу и к тому времени, когда это засыпает, использование RAM вернулось выше на приблизительно 600 МБ... хорошо, Вы видите, куда это идет...
Вопрос: я рассматриваю добавление сборки "мусора" непосредственно перед тем, как процесс засыпает. Существуют другие сервисы на это поле, которые делают связанные с.NET задачи. Когда я называю сборку "мусора" в этом сервисном процессе, что GC влияет на все другие связанные с.NET процессы на поле или просто процесс, который запрашивает набор? Я немного волнуюсь по поводу создания своего рода проблемы производительности для процессов за пределами того, о котором я забочусь.
Это просто влияет на процесс, в котором он вызывается (но влияет на все Application Domains в процессе). Однако, следует предупредить, что это не освободит память в операционной системе. Если вы хотите освободить память для операционной системы, способ сделать это следующий:
private static void minimizeMemory()
{
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
(UIntPtr) 0xFFFFFFFF, (UIntPtr) 0xFFFFFFFF);
}
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetProcessWorkingSetSize(IntPtr process,
UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);
Большая оговорка здесь: почему. Если только вы не заметили, что память "мотается" или "своппинг" является узким местом в производительности (или вы пишете приложение для конечного пользователя), то нет никаких реальных причин для беспокойства об использовании памяти. Принудительное использование памяти может быть медленным. Уменьшение кучи приведет к тому, что куча должна быть перераспределена из VM. Кроме того, .NET GC является реактивным, используя поведение программы для повышения ее эффективности. Принуждая коллекцию, вы не позволяете ГХ настроить себя в соответствии с поведением вашей программы, что еще больше снижает ее производительность.
Я знаю это по опыту -- некоторое время назад я задал этот вопрос и даже придумал класс, основанный на таймере, для вызова приведенного выше метода после выхода из операции с высокой памятью (запускается каждые 5 минут). После этого рабочий набор процесса сильно уменьшился бы -- путем замены его на диск. В течение следующих пары секунд он считывал наиболее часто используемые части, через пару минут (когда задача запускалась снова) он снова выполнял кучу распределений. Тайминг (даже не профилирование) процесса показал, что с коллекцией, было около 0.2s (!) замедление во время выделения ВМ из ОС для задачи.
Было бы разумно вытащить профилировщик и посмотреть, почему предметы не собираются эффективно. Возможно, они без необходимости попадают в ген2, и вы могли бы рефакторировать его, чтобы он быстрее избавлялся от предметов.
Вы также можете попробовать убедиться, что .NET часть работает с серверной версией сборщика мусора, по умолчанию это версия для рабочей станции, которая предпочитает держать процесс активным, а не работать с GC (т.е. она настроена так, чтобы пользовательский интерфейс был отзывчивым). Серверная версия более агрессивна и использует параллельные GC, однопроцессорное ядро.
Добавьте в app.config следующее:
<Configuration>
<runtime>
<gcServer enabled=“true“ />
</runtime>
</Configuration>
Ссылка на дополнительную информацию
Обычно это выражено Big or Onaination . В основном вы выбираете простую функцию (как N 2 , где n - количество элементов), которые доминируют на фактическом количестве итераций.
-121--3453565-Помимо дополнительного использования ЦП на протяжении всего сбора, заставить сборку мусора не приводит к воздействию на другие процессы .NET. Однако заставить сборку мусора не будет - в большинстве случаев - привести к выпуску физической памяти.
Отображение физической памяти к адресному пространству процесса является сложной вещью. Коллекция мусора в процессе .NET может увеличить свободное место в управляемой куче - но не гарантированно приведет к снижению размера рабочего набора (память вашего процесса Win32 подается из ОС). Даже если бы вы могли получить такую схему, работающую - это было бы хрупким в лучшем случае, и не может работать при любых обстоятельствах.
Существует метод Win32, называемый SetProcessworkingsEscingsEscize ()
, который позволяет контролировать минимальную и максимальную физическую память, выделенную для процесса. Вы можете захотеть посмотреть это в сочетании с принудительной схемы сбора, вы изучаете.
Наряду с другими ответами, относящимися непосредственно к использованию gc.collect, я бы предложил вам не только простую профилирование, но и сделать Обзор кода и убедитесь, что вы правильно выделяете ресурсы, когда вы сделаете их, используя их.
Вы называете утилизацию всех объектов, которые реализуются IDSPosable, когда вы сделаете их, используя их? Если у вас есть классы, которые содержат частные переменные, которые реализуются IDSPosable, содержит ли усомительный класс IDSPosable и вы звоните у Diswase?
Есть ли места, где вы можете использовать оператор с использованием, чтобы убедиться, что вызов Ни одно из этих вещей не поможет с физической памятью, но она поможет с такими вещами, как ручка к объектам Windows и т. Д.