Могу ли я ограничить HashMap объемом памяти, который он занимает? - PullRequest
3 голосов
/ 29 июля 2010

Я реализую простой кэш, используя LinkedHashMap на основе найденных инструкций здесь . Я использую следующий код:

public class Cache extends LinkedHashMap {
  private final int capacity;

  public Cache(int capacity) {
    super(capacity + 1, 1.1f, true);
    this.capacity = capacity;
  }

  protected boolean removeEldestEntry(Entry eldest) {
    return size() > capacity;
  }
}

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

Можно ли как-нибудь контролировать размер карты и ограничивать ее на основании этого?

Ответы [ 4 ]

3 голосов
/ 29 июля 2010

Если мягких / слабых ссылок не может быть и речи, то я вижу 2 (нетривиальных) варианта:

1) Используйте инструментарий Java для проверки фактического размера элементов, добавленных на карту.Интерфейс инструментария обеспечивает «мелкий» размер объекта, и вам потребуется больше кода для изучения ссылок (и во избежание подсчета дубликатов!). Здесь - это решение, которое вычисляет глубокий размер одного объекта.

2) Используйте JMX для отслеживания размера кучи после ГХ и изменения поведения карты при достижении некоторого опасного порога.См. Раздел «Уведомления» в MemoryMXBean javadoc .

2 голосов
/ 29 июля 2010

Сама карта содержит только записи фиксированного размера, которые содержат ссылки на фактические объекты, «содержащиеся» в карте. Вам необходимо переопределить все методы изменения карты (например, put(), конструктор копирования и т. Д.), Чтобы отслеживать размеры объектов, на которые ссылается карта (можно ли даже определить, сколько памяти занимает объект Java?) Затем учтите, что объекты, которые вы добавляете в кеш, сами могут содержать ссылки на другие объекты и / или коллекции. Как глубоко ты идешь?

Взгляните на http://www.javapractices.com/topic/TopicAction.do?Id=83

1 голос
/ 29 июля 2010

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

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

http://sizeof.sourceforge.net/

http://code.google.com/p/concurrentlinkedhashmap/

http://github.com/Omega1/voldemort/blob/master/src/java/voldemort/store/memory/ConcurrentLinkedHashMap.java

0 голосов
/ 29 июля 2010

Вы можете обернуть реализацию Map и применить размер в методах put и putAll.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...