Почему.NET не имеет SoftReference, а также WeakReference, как Java?
Я действительно люблю WeakReference. Но я хотел бы, чтобы был способ сообщить CLR, насколько (скажем, по шкале от 1 до 5), насколько слабой вы считаете ссылку. Это было бы замечательно.
У Java есть SoftReference, WeakReference и, я полагаю, также третий тип, называемый "фантомной ссылкой". Это 3 уровня, для которых у GC есть другой алгоритм поведения при принятии решения, получает ли этот объект отбивную.
Я подумываю о создании подкласса WeakReference.NET (к счастью и немного странного, он не запечатан), чтобы создать псевдо-SoftReference, который основан на таймере истечения срока действия или что-то в этом роде.
9 ответов
Я считаю, что фундаментальная причина того, что NET не имеет мягких ссылок, заключается в том, что она может полагаться на операционную систему с виртуальной памятью. Процесс Java должен указать свою максимальную память ОС (например, с -Xmx128M
), и это никогда не занимает больше памяти ОС, чем это. Принимая во внимание, что процесс NET продолжает забирать нужную ему память ОС, которую ОС снабжает виртуальной памятью на диске, когда заканчивается ОЗУ. Если NET разрешает мягкие ссылки, то среда выполнения NET не будет знать, когда их выпускать, если она либо не заглянет глубоко в ОС, чтобы увидеть, действительно ли ее память выгружена на диск (неприятная зависимость OS/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 минут, но большинство кешей никогда не гарантируют его сохранение. Он просто гарантирует, что если он это сделает, он истечет в соответствии с запрошенной политикой.
Мое предположение о том, почему этого уже нет, было бы просто. Большинство людей, я думаю, назвали бы это достоинством, что существует только один тип ссылки, а не четыре.
Может быть, класс ASP.NET Cache (System.Web.Caching.Cache) может помочь достичь того, чего вы хотите? Он автоматически удаляет объекты, если памяти становится мало:
Вот статья, которая показывает, как использовать класс Cache в приложении Windows Forms.
цитируется: эквивалентно SoftReference в.net?
Не забывайте, что у вас также есть стандартные ссылки (те, которые вы используете ежедневно). Это дает вам еще один уровень.
WeakReferences следует использовать, когда вы действительно не заботитесь о том, что объект исчезает, в то время как SoftReferences действительно следует использовать только тогда, когда вы используете обычную ссылку, но вы бы предпочли, чтобы ваш объект был очищен, тогда вам не хватило бы памяти. Я не уверен в деталях, но я подозреваю, что GC обычно отслеживает через SoftReferences, но не WeakReferences, когда определяет, какие объекты являются живыми, но при нехватке памяти также пропускает SoftReferences.
Я предполагаю, что.Net-дизайнеры почувствовали, что разница смущает большинство людей и что SoftReferences добавляют больше сложности, чем они на самом деле хотели, и поэтому решили оставить их без внимания.
Как примечание, AFAIK PhantomReferences в основном предназначены для внутреннего использования виртуальной машиной и не предназначены для фактического использования клиентом.
Может быть, должно быть свойство, в котором вы можете указать, в каком поколении объект>= перед его сбором. Так что, если вы укажете 1, то это самая слабая из возможных ссылок. Но если вы укажете 3, тогда потребуется пережить не менее 3 предыдущих коллекций, прежде чем их можно будет рассматривать для самой коллекции.
Я думал, что флаг восстановления трассы не годится для этого, потому что к тому времени объект уже был завершен? Может быть, неправильно, хотя...
(PS: я OP, только что зарегистрировался. PITA, что он не наследует вашу историю от "незарегистрированных" аккаунтов.)
Ищете опцию 'trackResurrection', переданную конструктору?
Класс GC также предлагает некоторую помощь.
Не знаю, почему.NET не имеет Softreferences. НО в Java Softreferences ИМХО злоупотребляют. Причина в том, что, по крайней мере, на сервере приложений вы хотели бы иметь возможность влиять на каждое приложение, как долго живет ваш Softreferenzen. В настоящее время это невозможно в Java.