#c# #garbage-collection
#c# #сбор мусора
Вопрос:
У меня есть простое приложение WPF, которое выделяет память, очищает ее и взаимодействует со сборщиком мусора. К сожалению, я никогда не вижу, чтобы собранный мусор автоматически очищал память. Например, скажем, я нажимаю кнопку Alloc 10 раз, она выделяет гигабайт, затем, если я нажимаю кнопку New, выделенная память не уменьшается. Однако, если я принудительно соберу мусор с помощью GC.Сбор (кнопка GC) освобождает память. Я включил большие коллекции с gcAllowVeryLargeObjects, для которых установлено значение true, так как я хотел бы протестировать использование более 2 гигабайт. Есть идеи, как я могу заставить сборщик мусора автоматически собирать и освобождать память?
Простой фрагмент кода:
List<byte[]> m_allocs = new List<byte[]>();
private void AllocClick(object sender, RoutedEventArgs e)
{
int oneHundredMegsAsBytes = 100000000;
byte[] array = new byte[oneHundredMegsAsBytes];
Array.Clear(array, 0, oneHundredMegsAsBytes);
m_allocs.Add(array);
}
private void NewClick(object sender, RoutedEventArgs e)
{
m_allocs = new List<byte[]>();
}
private void ClearClick(object sender, RoutedEventArgs e)
{
m_allocs.Clear();
}
private void GCClick(object sender, RoutedEventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
Комментарии:
1. Если в ОС все еще достаточно свободной памяти, GC пытается не запускаться, потому что в этом нет необходимости. Однако
Array.Clear()
в вашем примере ничего не делается — он просто устанавливает содержимое массива в значение по умолчанию для типа элемента массива; в вашем случае ноль — но массив уже содержит все нули. Это не изменяет размер массива.2. Сборка мусора происходит в какой-то неопределенный момент времени или, возможно, никогда, если памяти достаточно. Он не спешит освобождать память при первой возможности.
3. И имейте в виду, что вся причина существования GC заключается в том, чтобы позволить разработчикам не беспокоиться об управлении памятью. Вам не нужно тестировать GC, он действительно работает.
Ответ №1:
Вы этого не делаете.
GC был разработан для запуска только при необходимости. Если ваш не запущен, то в этом нет необходимости.
Вы этого не хотите.
GC стоит дорого, GC должен остановить программу и выяснить, что нужно, а что нет. Если бы он делал это в конце каждого цикла, ваша программа выполняла бы обход.
Однако…
Вы могли бы изменить процентное значение с большим объемом памяти на меньшее значение, что сделает GC намного более агрессивным, намного раньше. Вероятно, это принесет вам больше вреда, чем пользы.
Ответ №2:
При экспериментировании на основе новой информации из ваших комментариев я нашел решение. Если я нажимаю alloc много раз, например, до использования 10 гигабайт, затем нажимаю очистить и продолжаю выделять больше, в конечном итоге использование памяти снижается до более низкого значения, например, 2 гигабайта.
Таким образом, сборщик мусора автоматически запускается с образцом кода, он просто работает, когда использование памяти выше, чем я тестировал, и помогают дополнительные выделения.