Цель GC.Collect () - PullRequest
       22

Цель GC.Collect ()

0 голосов
/ 11 июня 2019

Я новичок в .NET и CLR, просто вопрос по сборке мусора в CLR.

В моем учебнике описана одна из целей использования GC.Collect ():

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

Ниже мой код:

Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));
Car refToMyCar = new Car();
Console.WriteLine("\nGeneration of refToMyCar is: {0}", GC.GetGeneration(refToMyCar));
GC.Collect(0, GCCollectionMode.Forced);
Console.WriteLine("\nGeneration of refToMyCar is: {0}", GC.GetGeneration(refToMyCar));
Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));

и выход:

Estimated bytes on heap: 29900

Generation of refToMyCar is: 0

Generation of refToMyCar is: 1

Estimated bytes on heap: 39648

вот мой вопрос:

1 - GC.Collect (), кажется, отмечает только элемент, указанный refToMyCar от Поколения 0 до Поколения 1, ничто не было «свободным», так как Поколение 1 означает объект, который пережил сборку мусора. Скажем, перед GC.Collect () в куче осталось 10 МБ доступного размера (например, всего 100 МБ), а после GC.Collect () в куче осталось всего 10 МБ, так какой смысл вызывать GC .Collect ()? Разве мы не хотим, чтобы доступный размер был 100 МБ 100%?

EDIT: Отменить мой предыдущий вопрос

если я изменю его на массив объектов, он будет еще более странным:

Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));
object[] refToMyCar = new object[50000];
for (int i = 0; i < 50000; i++)
   refToMyCar[i] = new object();
Console.WriteLine("\nGeneration of refToMyCar is: {0}", GC.GetGeneration(refToMyCar));       
Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));

вывод:

Estimated bytes on heap: 29900

Generation of refToMyCar is: 2
Estimated bytes on heap: 836140
Press any key to continue . . .

Почему refToMyCar - это Поколение 2, которое является объектом, пережившим более одного цикла сбора мусора? мы еще не вызывали неявный или явный GC.Collect ()?

Ответы [ 2 ]

3 голосов
/ 11 июня 2019

Сборщик мусора не имеет права собирать объекты, на которые все еще есть ссылки.Поскольку вы сохраняете ссылку на refToMyCar, чтобы получить ее генерацию позже, она не может быть собрана.Если вы хотите наблюдать за возвращаемым объектом, вы можете использовать WeakReference.Кроме того, вам нужно работать без отладчика - чтобы помочь с отладкой, отладчик делает так, чтобы все ссылки выжили, пока они не выйдут из области видимости (т. Е. Тело блока / метода завершится).

Во втором случаеВы выделяете большой объект..NET поместит их в специальную кучу, кучу больших объектов.У этих объектов есть особые правила - они всегда считаются вторым поколением, и их нельзя перемещать (если вы явно не попросите GC сделать это).Вы должны уделять особое внимание крупным объектам.

Конечно, оба эти поведения описаны в документации .

Основное правило, касающееся GC.Collect, довольно просто - не используйте его.В очень редких случаях это дает какую-то выгоду, и в большинстве случаев вы просто тратите ресурсы ЦП, памяти и заставляете объекты выживать на дольше , чем они в противном случае.

0 голосов
/ 11 июня 2019

После вашего GC.Collect() вы используете переменную, которую пытаетесь собрать:

Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));
Car refToMyCar = new Car();
Console.WriteLine("\nGeneration of refToMyCar is: {0}", GC.GetGeneration(refToMyCar));
GC.Collect(0, GCCollectionMode.Forced);

// after removing reference to the variable it's been collected and will not survive to generation 1
// Console.WriteLine("\nGeneration of refToMyCar is: {0}", GC.GetGeneration(refToMyCar));
Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));

Это происходит из-за того, как осуществляется управление памятью, и если где-то в вашем коде вы ссылаетесь на переменную - она ​​выживет и ее генерация может быть обновлена. Вот почему вы должны быть осторожны с замыканиями и древовидными структурами.

Выход:

Estimated bytes on heap: 29988

Generation of refToMyCar is: 0
Estimated bytes on heap: 29448

Что касается других ваших вопросов - я полагаю, что вы не можете освободить 100% кучи памяти только потому, что вам нужно где-то хранить саму программу, выделение памяти статическим классом - хорошим примером этого является GC.

...