Любые Java-кэши, которые могут ограничить использование памяти кэша в памяти, а не только количество экземпляров?

Я ищу простой кэш в памяти (и в процессе) для краткосрочного кэширования данных запроса (но краткосрочного значения за пределами запроса/ответа, т. е. границы сеанса). EhCache, вероятно, будет работать, но похоже, что он не может предложить одну вещь, которая мне нужна: ограничения не на количество кэшированных объектов, а (приблизительное) ограничение на объем памяти, потребляемой кэшированными данными.

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

Итак: есть ли простой кэш java с открытым исходным кодом, который позволяет определить "вес" кэшированных объектов, чтобы ограничить количество кэшируемых вещей?

EDIT (Nov 2010): для чего это стоит, есть новый проект под названием Java CacheMate что пытается решить эту проблему, наряду с некоторыми другими идеями улучшения (многоуровневое кэширование в памяти в процессе)

8 ответов


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

размер памяти можно определить, включив агент Java, и использование довольно просто, когда использование утилиты SizeOf (http://sourceforge.net/projects/sizeof). Я использовал это только для отладки, и я бы рекомендовал бенчмаркинг накладных расходов, прежде чем принимать его для нормального использования.

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

Если вам это действительно нужно, и я бы не советовал, мы могли бы улучшить мою текущую реализацию, чтобы поддержать это. Вы можете написать мне, ben.manes-at-gmail.com.


Как насчет использования простого LinkedHashMap с включенным алгоритмом LRU и поместить в него все данные с SoftReference... например, кэш.out (ключ, новый SoftReference (значение))??

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

это освободит вас от вычисления размера записей и отслеживания суммы.


EhCache V2.5 в настоящее время предлагает решение, которое может cap на основе размера памяти кэша. Для получения более подробной информации проверки Документация EhCache 2.5


Это не просто трудно измерить - это трудно определить.

предположим, что две записи кэша относятся к одной и той же строке - do they и подсчитайте размер этой строки, несмотря на то, что удаление любого из них из кэша не сделает строку подходящей для сбора мусора? Ни один из них не считает размер, несмотря на то, что if и из них удаляются из кэша, то строка может иметь право на сбор? Как насчет, если другой объект, не находящийся в кэше, имеет ссылку на эту строку?

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


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


Если вы не можете сделать какие - либо оценки-напишите политику вытеснения кэша, которая сбрасывается на основе размера кучи JVM (опрошенного из системы) или вызванного finalize () - вызовом из потерянного объекта (на GC).


можно определить значимую меру для использования памяти кэша. Вы можете вычислить : "сохранить размер". К сожалению, вычисление сохраненного размера примерно так же дорого, как полный GC, и поэтому это, вероятно, не вариант. На некоторых языках JVM (clojure?) теоретически вы можете убедиться, что никакие объекты в кэше не будут ссылаться на внешние объекты, а затем вы можете контролировать реальный размер кэша.


то, что делает эту работу, - это java.ленг.ссылка.SoftReference . Обычно класс SoftReference расширяется таким образом, чтобы подкласс содержал ключ.