2008-11-27 10 views
13

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

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

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

+2

Возможно, если вы объясните, в чем проблема, которую вы пытаетесь решить, вы можете получить ответы с хорошими решениями. Обычно это нехорошо работать на этом уровне детализации, и некоторая форма кэша срока действия более уместна, но все зависит от проблемы. – 2008-11-28 01:37:30

ответ

4

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

+3

на самом деле SoftReferences чрезвычайно полезны, поскольку они позволяют кэшировать чувствительные к памяти gc. Большинство людей, которые действительно понимают, что они хотят, хотели бы иметь их. В Java-коде я чаще использую SoftReference MUCH, а затем WeakReference – user430788 2014-04-03 17:42:09

0

Ищете опцию 'trackResurrection', переданную конструктору, возможно?

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

1

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

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

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

4

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

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

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

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

+0

. Различие заключается в том, что использование SoftReference в кеше позволяет хранить вещи до тех пор, пока для них достаточно памяти, но утилизируйте их, если нет. Это гораздо более эффективное решение, а затем тайм-аут в кеше. – user430788 2014-04-03 17:44:05

+0

@ user430788 Думаю, вам не хватает моего комментария о кешах. Кэш может использовать WeakReference уже, но постоянство может также применяться к кешированным элементам. С точки зрения потребителя кэша кеш обычно не гарантирует, что элементы будут оставаться в кеше.Devs уже жалуются на GC, поэтому, возможно, команда C# почувствовала, что добавление новых уровней слабых ссылок (soft, phantom) не добавило достаточно. Как всегда, Эрик Липперт http://blogs.msdn.com/b/ericlippert/archive/2003/10/28/how-many-microsoft-employees-does-it-take-to-change-a-lightbulb.aspx является хорошим для понимания возможностей C#. – 2014-04-03 22:14:17

+1

Роберт, боюсь, вы меня совсем не поняли. Нет, кеш не гарантирует, что вещи остаются в кеше. В этом-то и дело. Но кеш, основанный исключительно на времени, не помогает определить, что должно и не должно быть в памяти. Это сбрасывает все без причины. Кэш, основанный на потребностях в памяти, намного лучше сохраняет данные, если это действительно нужно удалить. Вы МОЖЕТЕ реализовать свой кеш LRU самостоятельно, но для этого вам потребуется добавить код управления псевдо-памятью. Его гораздо эффективнее позволить GC, который уже управляет памятью, управляет вашим кешем. – user430788 2014-04-23 00:49:56

0

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

+0

В HotSpot есть одна возможность настроить это немного: -XX: SoftRefLRUPolicyMSPerMB = xyz. См. Http://java.sun.com/docs/hotspot/HotSpotFAQ.html#gc_softrefs – 2009-02-05 01:19:32

2

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

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

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

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

+1

См. Мои комментарии выше о том, насколько полезны SoftRefernces и как они могут позволить вам код более эффективно. Phantom References подходит для тех, кто действительно нуждается в очистке от посмертных вещей. – user430788 2014-04-03 17:45:07

3

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

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

цитировал: Equivalent to SoftReference in .net?

16

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

11

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

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