Какой смысл использовать GC.AddMemoryPressure с неуправляемым ресурсом?

Я читал об этой проблеме в MSDN и CLR через С#.

Представьте себе, что у нас есть 2Mb неуправляемый HBITMAP и 8-битная управляемая растровая карта, указывающая на него. Какой смысл сообщать GC об этом с помощью AddMemoryPressure, если он никогда не сможет ничего сделать о объекте, поскольку он выделяется как неуправляемый ресурс, таким образом, не подвержен сборам мусора?

Ответ 1

Точка AddMemoryPressure заключается в том, чтобы сообщить сборщику мусора, что там выделен большой объем памяти. Если он неуправляемый, сборщик мусора не знает об этом; только управляемая часть. Поскольку управляемая часть относительно невелика, GC может позволить ей проходить сборку мусора несколько раз, по существу тратя память, которую, возможно, нужно будет освободить.

Да, вам все равно придется вручную выделять и освобождать неуправляемую память. Вы не можете уйти от этого. Вы просто используете AddMemoryPressure, чтобы гарантировать, что GC знает об этом.

Edit:

Ну, в случае одного, я мог бы это сделать, но это не имело большого значения, поскольку GC не смог бы что-либо сделать по моему типу, если я правильно понял: 1) объявить мою переменную, 8 управляемых байтов, 2 мб неуправляемых байтов. Затем я буду использовать его, вызывать dispose, поэтому неуправляемая память освобождается. Сейчас это будет только ocuppy 8 байтов. Теперь, на мой взгляд, вызвав в начале AddMemoryPressure и RemoveMemoryPressure в конце, не было бы ничего другого. Что я ошибаюсь? Извините за то, что я так беспокоюсь об этом. - Хорхе Бранко

Я думаю, что вижу вашу проблему.

Да, если вы можете гарантировать, что вы всегда вызываете Dispose, то да, вам не нужно беспокоиться об AddMemoryPressure и RemoveMemoryPressure. Эквивалентности нет, так как ссылка все еще существует, и тип никогда не будет собран.

Тем не менее, вы по-прежнему хотите использовать AddMemoryPressure и RemoveMemoryPressure для полноты. Что, если, например, пользователь вашего класса забыл вызвать Dispose? В этом случае, предположив, что вы правильно реализовали шаблон Disposal, вы завершите восстановление неуправляемых байтов при завершении, т.е. При сборке управляемого объекта. В этом случае вы хотите, чтобы давление памяти все еще было активным, так что объект, скорее всего, будет восстановлен.

Ответ 2

Он предоставляется, чтобы GC знал истинную стоимость объекта во время сбора. Если объект на самом деле больше, чем отражает размер управляемого размера, он может быть кандидатом для быстрой (er) коллекции.

Brad Abrams запись об этом довольно ясно:

Рассмотрим класс, который имеет очень маленький размер управляемого экземпляра, но указатель на очень большой кусок неуправляемая память. Даже после того, как никто ссылается на управляемый экземпляр может остаться в живых на некоторое время, потому что GC видит только управляемый экземпляр размер он не думает, что это "стоит это", чтобы освободить экземпляр. "научить" GC об истинной стоимости этого экземпляра, чтобы он точно знать, когда ударить коллекции, чтобы освободить больше памяти в процесс.

Ответ 3

Положите это так, все еще предполагая, что 8-байтные управляемые объекты ссылаются на 2-х неуправляемое изображение. GC может долго ждать, прежде чем собирать сотни или тысячи маленьких управляемых объектов, потому что они настолько малы. Это означало бы, что сотни или тысячи связанных 2 000 неуправляемых блоков останутся в живых, ожидая удаления. Это может стать огромной проблемой. Добавив в конструктор 2 МБ давления памяти, вы сделаете GC, думая, что управляемый объект не имеет 8 байтов, а скорее 8 байтов + 2 МБ. Это приведет к началу сбора данных.

Не забывайте, что вызов "Удалить".

Конечно, если вы распорядитесь собой, вам это не понадобится.