2009-07-19 4 views
12

Я читал об этой проблеме в MSDN и на CLR через C#.Какой смысл использовать GC.AddMemoryPressure с неуправляемым ресурсом?

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

ответ

9

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

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

Edit:

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

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

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

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

+0

Ну, это не ответило на вопрос, lol. –

+0

Я сказал почти точно, что сказал Стивен Лионс, только по-другому. Как это не ответило на вопрос? – Randolpho

+0

Ну, на самом деле я перечитал его и отредактировал свой пост. –

13

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

Брэд Абрамс entry об этом довольно ясно:

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

+0

На самом деле, теперь, когда я перечитываю ваше сообщение, мой вопрос стоит на месте. После того, как я использую свой растровый рисунок, я буду называть его dispose, поэтому на самом деле это займет всего 8 байт. Если с другой стороны, я не вызывал dispose, ну, тогда он действительно окупирует 2 Мб памяти. Существует 3-й случай, когда метод размещения отсутствует, поэтому GC ничего не может сделать для него. Итак, GC, зная реальный размер типа, поможет только в ситуации 2. Или я что-то упускаю? –

+0

В случае 1 вам нужно будет вызвать GC.AddMemoryPressure для выделения растрового изображения, а затем GC.RemoveMemoryPressure, когда вы вручную отпустите растровое изображение. Это гарантирует, что объект правильно отражает его размер для GC. Однако, если есть способ убедиться, что GC никогда не запускается, пока ваш объект имеет право на сбор, а растровое изображение выделено, эти методы могут не иметь значения. –

+0

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

2

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

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

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

Смежные вопросы