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

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

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

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


person Community    schedule 27.11.2008    source источник
comment
Может быть, если вы объясните, какую проблему вы пытаетесь решить, вы можете получить ответы с хорошими решениями. Обычно работать на таком уровне детализации не рекомендуется, и более подходящей является некоторая форма кеша с истекающим сроком действия, но все зависит от проблемы.   -  person Pop Catalin    schedule 28.11.2008


Ответы (9)


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

person Adam Gawne-Cain    schedule 18.08.2011
comment
Но, возможно, для .Net Compact такая штука могла бы пригодиться. - person i486; 15.02.2016

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

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

person barneypitt    schedule 15.09.2012
comment
Это действительно хороший указатель, и он должен быть на вершине ответов. - person user430788; 03.04.2014
comment
Это хорошее дополнение, но меня удивляет его гибкость. В целом я предпочитаю открытые механизмы черным ящикам дилеров. Они, как правило, более полезны в реальном мире производства. (Конечно, GC сам по себе является запечатанным черным ящиком, но, по крайней мере, Java позволяет вам заменить весь сборщик, если вы действительно этого хотите.) - person user430788; 23.04.2014
comment
Я согласен, в целом я предпочитаю открытые механизмы черным ящикам, и это одна из причин, по которой я предпочитаю Java C#. Но, с другой стороны, каждый новый сборщик мусора Java требует собственной реализации SoftReferences, которая легко может быть менее подходящей для ваших целей, чем ваш текущий сборщик мусора. И изменение GC — это нелегкая задача (по крайней мере, в среде с малой паузой/малой задержкой). - person barneypitt; 02.04.2015

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

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

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

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

person Robert Paulson    schedule 28.11.2008
comment
Разница в том, что использование SoftReference для кэширования позволяет вам хранить объекты, пока для них достаточно памяти, но удалять их, если этого недостаточно. Это намного более эффективное решение, чем тайм-аут кэша. - person user430788; 03.04.2014
comment
@user430788 user430788 Я думаю, вы пропустили мой комментарий о кешах. Кэш уже может использовать WeakReference, но устаревание также может относиться к кэшированным элементам. С точки зрения потребителя кеша, кеш обычно не гарантирует, что элементы останутся в кеше. Разработчики уже жалуются на сборщик мусора, поэтому, возможно, команда C# посчитала, что добавление новых уровней слабых ссылок (мягких, фантомных) недостаточно. Как всегда, blogs.msdn.com/b/ericlippert/archive/2003/10/28/ хорошо подходит для понимания возможностей C#. - person Robert Paulson; 04.04.2014
comment
Роберт, боюсь, вы совсем меня не поняли. Нет, кеш не гарантирует, что вещи останутся в кеше. В этом-то и дело. Но кеш, основанный исключительно на времени, не очень хорошо определяет, что должно и не должно быть в памяти. Он смывает вещи без причины. Кэш, основанный на потребностях в памяти, намного лучше сохраняет данные, если их действительно не нужно удалять. Вы МОЖЕТЕ реализовать кэш LRU самостоятельно, но для этого потребуется добавить код управления псевдопамятью в ваше приложение. Гораздо эффективнее позволить GC, который уже управляет памятью, управлять вашим кешем. - person user430788; 23.04.2014

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

person TheSmurf    schedule 27.11.2008
comment
на самом деле SoftReferences ЧРЕЗВЫЧАЙНО полезны, поскольку они позволяют кэшировать память с учетом gc. Большинство людей, которые на самом деле понимают, для чего они нужны, хотели бы их иметь. В Java-коде я использую SoftReference НАМНОГО чаще, чем WeakReference. - person user430788; 03.04.2014

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

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

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

person sumek    schedule 18.02.2010

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

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

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

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

person James    schedule 19.01.2009
comment
См. мои комментарии выше о том, насколько полезны SoftRefernces и как они могут помочь вам писать код более эффективно. Фантомные ссылки предназначены для тех, кому действительно нужно провести какую-либо очистку после смерти. - person user430788; 03.04.2014

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

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

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

person nbevans    schedule 27.11.2008

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

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

person leppie    schedule 27.11.2008

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

person kohlerm    schedule 19.01.2009
comment
В HotSpot есть один вариант немного настроить это: -XX:SoftRefLRUPolicyMSPerMB=xyz. См. java.sun.com/docs/hotspot/HotSpotFAQ.html#gc_softrefs - person Luke Quinane; 05.02.2009