Кэш, поддерживающий память Java - PullRequest
4 голосов
/ 30 августа 2011

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

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

Существуют ли методы для определения того, сколько памяти используется? Или лучше полагаться на мягкие указатели? Программный указатель и работа всегда в верхней части лимита памяти jvm могут быть очень неэффективными с большим количеством циклов процессора для очистки памяти? Могу ли я провести некоторый анализ существующих объектов, например myObject.getMemoryUsage()?

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

Какая самая лучшая практика?

Ответы [ 4 ]

2 голосов
/ 30 августа 2011

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

Вы можете использовать Instrumentation.getObjectSize (), чтобы получить малый размер объекта и использовать отражение, чтобы получить глубокий размер. Однако делать это относительно дорого, а не то, что вы хотите делать очень часто.

Почему вы не можете ограничить размер количеством объектов? На самом деле, я бы начал с самого простого кеша, который вы можете, и добавил бы только то, что вам действительно нужно.

LRU-кеш в Java.

РЕДАКТИРОВАТЬ: Один из способов отследить, сколько памяти вы используете, состоит в том, чтобы сериализовать значение и сохранить его как байт []. Это может дать вам довольно точное управление, но может замедлить ваше решение до 1000 раз. (Ничто не приходит бесплатно;)

1 голос
/ 01 сентября 2011

Проблема с SoftReferences состоит в том, что они дают больше работы сборщику мусора.Хотя это не отвечает вашим требованиям, HBase имеет очень интересную стратегию, чтобы предотвратить использование кэшем пауз для сборки мусора: они хранят кэш в собственной памяти:

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

1 голос
/ 30 августа 2011

Я бы рекомендовал использовать Java Caching System .Хотя, если вы захотите свернуть свои собственные, я не знаю ни одного способа получить размер объектов в памяти.Лучше всего было бы расширить AbstractMap и обернуть значения в SoftReferences.Затем вы можете установить размер кучи Java на максимальный размер, который вы хотели.Тем не менее, ваша реализация также должна найти и очистить устаревшие данные.Наверное, проще всего использовать JCS.

0 голосов
/ 02 ноября 2011

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

При использовании GC стоит много денег.

EHCacheодин из самых популярных, о которых я знаю.Java Caching System из другого ответа также хороша.

Тем не менее, я обычно переложу эту работу на базовую функцию (обычно на уровне персистентности JPA сервером приложений, поэтому я позволяю ему обрабатываться там, поэтому я неприходится иметь дело с этим на уровне приложения).

Если вы кэшируете другие данные, такие как веб-запросы, http://hc.apache.org/httpclient-3.x/ также является другим хорошим кандидатом.

Однако, просто помнитеу вас также есть «файловая система», нет ничего плохого в том, чтобы записать в данные файловой системы, которые вы получили.Я использовал эту технику несколько раз, чтобы исправить ошибки памяти из-за неправильного использования ByteArrayOutputStreams

...