Стоимость использования слабых ссылок в Java - PullRequest
46 голосов
/ 09 августа 2009

Кто-нибудь исследовал затраты времени выполнения, связанные с созданием и сборкой мусора Java WeakReference объектов? Есть ли проблемы с производительностью (например, конфликты) для многопоточных приложений?

РЕДАКТИРОВАТЬ: Очевидно, что фактические ответы будут зависеть от JVM, но общие наблюдения также приветствуются.

РЕДАКТИРОВАТЬ 2: Если кто-то провел какой-либо сравнительный анализ производительности или может указать на некоторые результаты сравнительного анализа, это было бы идеально. (Извините, но щедрость истекла ...)

Ответы [ 3 ]

13 голосов
/ 13 августа 2009

Слабые ссылки негативно влияют на сборщик мусора CMS. Насколько я могу судить по поведению нашего сервера, это влияет на время фазы параллельного замечания. На этом этапе все потоки приложения останавливаются, поэтому это крайне нежелательно. Поэтому вы должны быть осторожны с WeakReferences.

5 голосов
/ 10 июля 2015

Я реализовал Java-сборщик мусора один раз, поэтому все, что мне удалось сделать, - это (слабая :) нижняя граница того, что возможно.

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

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

Самое главное, стоимость пропорциональна количеству существующих слабых ссылок, а не размеру общей кучи.

Однако это не означает, что сборщик мусора, который поддерживает слабые ссылки, будет работать так же быстро, как и тот, который не поддерживает. Предполагаемый вопрос здесь, учитывая, что Java поддерживает слабые ссылки, какова дополнительная стоимость их использования?

Шахта была простой меткой "останови мир" / выметала мусорщик. Во время сборки мусора он определяет для каждого объекта, является ли этот объект живым или нет, и устанавливает бит LIVE в заголовке объекта. Затем он проходит и освобождает все неживые объекты.

Для обработки слабых ссылок вы просто добавляете следующее:

  • Игнорировать слабые ссылки при установке битов LIVE (т. Е. Они не приводят к установке бита LIVE на ссылочный объект).
  • На этапе развертки добавьте специальную проверку следующим образом: если объект, который вы посещаете, равен LIVE, и это WeakReference, то проверьте объект, на который он слабо ссылается, и если этот объект не LIVE, очистить ссылку.

Небольшие вариации этой логики работают для мягких и фантомных ссылок.

Реализация здесь , если вам действительно любопытно.

3 голосов
/ 03 февраля 2013
Кэш

с использованием слабых ссылок может значительно замедлить работу вашего приложения, если оно будет перестроено по требованию, например, в геттерах:

public Object getSomethingExpensiveToFind() {
    if(cache.contains(EXPENSIVE_OBJ_KEY)) {
        return cache.get(EXPENSIVE_OBJ_KEY);
    }

    Object sth = obtainSomethingExpensiveToFind(); // computationally expensive
    cache.put(EXPENSIVE_OBJ_KEY, sth);
    return sth;
} 

представьте себе такой сценарий:

1) приложению не хватает памяти

2) GC очищает слабые ссылки, поэтому очищается и кеш

3) приложение продолжается, вызывается множество методов, таких как getSomethingExорогоToFind () и перестраивается кеш

4) приложению снова не хватает памяти

5) GC очищает ссылки на износ, очищает кэш

6) приложение продолжается, вызывается множество методов, таких как getSomethingExadvanToFind (), и снова перестраивает кэш

7) и так далее ...

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

Другими словами, при неправильном управлении слабые ссылки могут замедлить работу вашего приложения.

...