Почему .NET не имеет SoftReference, а также WeakReference, например Java?

Я действительно люблю WeakReference. Но я хотел бы, чтобы был способ сообщить CLR, сколько (скажем, по шкале от 1 до 5), насколько слаб вы считаете ссылкой. Это было бы блестяще.

Java имеет SoftReference, WeakReference, и я также считаю, что третий тип называется ссылкой phantom. Это 3 уровня прямо там, где GC имеет другой алгоритм поведения при принятии решения о том, получает ли этот объект прерывание.

Я подумываю о подклассе .NET WeakReference (к счастью и чуть-чуть-чуть не запечатанном), чтобы создать псевдо-SoftReference, основанный на таймере истечения срока действия или что-то в этом роде.

9 ответов

Я считаю, что основная причина, по которой NET не имеет мягких ссылок, заключается в том, что она может полагаться на операционную систему с виртуальной памятью. Процесс Java должен указывать максимальную ОС-память (например, с -Xmx128M), и он никогда не занимает больше памяти ОС, чем это. Принимая во внимание, что процесс NET продолжает использовать память ОС, которая ему нужна, которую ОС поставляет с виртуальной памятью с дисковым резервным копированием, когда операционная система заканчивается. Если NET разрешает использование софт-ссылок, тогда среда выполнения NET не будет знать, когда ее выпускать, если она не заглянет глубоко в ОС, чтобы проверить, действительно ли ее память загружена на диск (неприятная зависимость ОС /CLR ) или запросила время выполнения укажите максимальный объем памяти процесса (например, эквивалент -Xmx). Я полагаю, что Microsoft не хочет добавлять -Xmx в NET, потому что они думают, что ОС должна решить, сколько ОЗУ каждого процесса получает (путем выбора страниц виртуальной памяти для хранения в ОЗУ или на диске), а не самого процесса.


Java SoftReferences используются при создании кэшей с памятью (они не предназначены для других целей).

Начиная с .NET 4,.NET имеет класс System.Runtime.Caching.MemoryCache, который, вероятно, удовлетворит любые такие потребности.


Наличие WeakReference с различными уровнями слабости (приоритет) звучит неплохо, но также может затруднить работу GC, а не проще. (Я понятия не имею о внутренних компонентах GC, но) Я бы предположил, что есть какие-то дополнительные статистики доступа, которые хранятся для объектов WeakReference, чтобы GC мог их эффективно очистить (например, он мог бы избавиться от наименее используемых элементов первый).

Более вероятно, что добавленная сложность не сделает ничего более эффективным, потому что наиболее эффективным способом является избавление от редко используемых WeakReferences. Если бы вы могли назначить приоритет, как бы вы это сделали? Это пахнет преждевременной оптимизацией: программист на самом деле не знает большую часть времени и догадывается; результатом является медленный цикл сбора GC, который, вероятно, восстанавливает неправильные объекты.

Он задает вопрос, хотя, если вы заботитесь о том, чтобы объект WeakReference.Target был исправлен, действительно ли это полезно использовать WeakReference?

Он похож на кеш. Вы загружаете материал в кеш и просите кеш сделать его устаревшим через x минут, но большинство кешей никогда не гарантируют, что он будет содержать его вообще. Это просто гарантирует, что если это произойдет, оно истечет в соответствии с запрошенной политикой.


Мое предположение о том, почему этого нет, уже было бы простотой. Большинство людей, я думаю, назову это добродетелью, что есть только один тип ссылок, а не четыре.


Может быть, класс Cache ASP.NET(System.Web.Caching.Cache) может помочь вам достичь того, чего вы хотите? Он автоматически удаляет объекты, если память становится низкой:

Вот статья, в которой показано, как использовать класс Cache в приложении форм Windows.

цитата из: Эквивалентна SoftReference в .net?


Не забывайте, что у вас также есть свои стандартные ссылки (те, которые вы используете ежедневно). Это дает вам еще один уровень.

WeakReferences следует использовать, когда вам действительно неинтересно, если объект уходит, а SoftReferences действительно должен использоваться только тогда, когда вы будете использовать обычную ссылку, но вы предпочли бы, чтобы ваш объект был очищен, а затем вы исчерпали Память. Я не уверен в специфике, но я подозреваю, что GC обычно отслеживает SoftReferences, но не WeakReferences при определении того, какие объекты живут, но при запуске с низким объемом памяти также будут пропускаться SoftReferences.

Моя догадка заключается в том, что разработчики .Net считали, что эта разница сбивает с толку большинство людей и что SoftReferences добавляют больше сложности, чем они действительно хотели, и поэтому решили оставить их.

В качестве дополнительной заметки AFAIK PhantomReferences в основном предназначены для внутреннего использования виртуальной машиной и не предназначены для фактического использования клиентом.


Может быть, должно быть свойство, в котором вы можете указать, какое из поколений должно быть объектом → до его сбора. Поэтому, если вы укажете 1, это будет самая слабая возможная ссылка. Но если вы укажете 3, тогда вам нужно будет выжить как минимум 3 предыдущих коллекций, прежде чем их можно будет рассмотреть для самой коллекции.

Я думал, что флаг повторения дорожки не подходит для этого, потому что к тому времени объект уже был финализирован? Может быть, ошибается, хотя...

(PS: Я OP, только что зарегистрировался. PITA, что он не наследует вашу историю из "незарегистрированных" учетных записей.)


Не знаю, почему .NET не имеет Softreferences. НО в Java Softreferences IMHO злоупотребляют. Причина в том, что, по крайней мере, на сервере приложений вы хотели бы иметь возможность влиять на каждое приложение, как долго живет ваш Softreferenzen. В настоящее время это невозможно в Java.


Ищете параметр trackResurrection, переданный конструктору, возможно?

Класс GC также предлагает некоторую помощь.

licensed under cc by-sa 3.0 with attribution.