Как реализовать кэш записи, который подменяет данные на диск только при нехватке свободной памяти - PullRequest
3 голосов
/ 08 декабря 2011

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

В идеале я хотел бы, чтобы виртуальная машина уведомила меня, что ей требуется памятьи записать мои данные на диск и освободить память таким образом.Но я не вижу способа подключиться к виртуальной машине таким образом, чтобы уведомить меня до того, как и OutOfMemoryError произойдет где-то (скорее всего, в коде, никак не связанном с кешем).

Справочные классы в java.lang.ref, по-видимому, не имеют никакого смысла в этом случае, их механизм уведомления (ReferenceQueue) срабатывает только после того, как ссылка уже была восстановлена ​​GC.Тогда было бы слишком поздно сохранять данные на диск.

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


Edit1 : в ответ на комментарий «ОС уже делает это для вас» - это касается только части проблемы -объем памяти, который ОС может выделить , является ограниченным ресурсом .Существуют и другие ограничения, помимо объема памяти, доступной для ОС, которые необходимо учитывать здесь:

  • Ограничение, налагаемое архитектурой виртуальной машины (32-Bit VM)
  • Ограничениепамяти, которая может быть выделена для процесса виртуальной машины (32-Bit OS)
  • Ограничение, возможно, наложенное на виртуальную машину с использованием опции -Xmx

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

Ответы [ 5 ]

1 голос
/ 08 декабря 2011

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

См. этот вопрос о том, как отслеживать объем свободной памяти, доступной для JVM.

0 голосов
/ 14 февраля 2012

Рассматривали ли вы использование отображенных в память файлов?См. http://en.wikipedia.org/wiki/Memory-mapped_file

Это решает вашу проблему, связанную с невозможностью доступа к памяти, превышающей объем, выделенный для виртуальной машины.

0 голосов
/ 08 декабря 2011

Это очень трудно сделать в чистой Java по тем причинам, на которые вы уже намекали.

  • Вполне нормально, что куча становится почти заполненной до того, как GC пинаетТаким образом, единственный способ определить, сколько свободной памяти действительно доступно, - это выполнить ГХ (и вы не хотите делать это слишком часто).Вы могли бы использовать опцию CMSInitiatingOccupancyFraction, чтобы убедиться, что GC происходит, когда perm gen заполнен (скажем) на 80% - тогда вы могли бы предположить, что значение «свободной памяти», возвращаемое API управления, вероятно, является правильным (для значений> 80%),Но, конечно, нет никакой гарантии.

  • Как вы упоминали, сборщики автоматически очищают сборщик перед добавлением в очереди, в которых они зарегистрированы, поэтому они не особеннополезно здесь.Вы могли бы создать фиктивную SoftReference и использовать ее запрос в качестве индикатора того, что памяти мало.Но я не уверен насчет времени. Можете ли вы гарантировать сброс всех ваших данных на диск до того, как JVM исчерпает память?Вероятно, нет.

Не могли бы вы вместо этого сбросить кэш на диск, когда он достигнет определенного размера , например, если он превышает 500 МБ, затем очистить его?

Или вы можете использовать MappedByteBuffer с приватным отображением - тогда данные не будут сброшены на диск?Если я правильно помню, данные, которые вы пишете, хранятся в «прямой» памяти вне кучи (по крайней мере, в Linux) и поэтому не будут занимать вашу кучу, но, пожалуйста, проверьте это.Если ОЗУ истощится, вы, конечно, начнете использовать Swap.

0 голосов
/ 08 декабря 2011

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

0 голосов
/ 08 декабря 2011

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

...