Избегайте «ошибки нехватки памяти» в Java (eclipse) при использовании большой структуры данных?

StackOverflow https://stackoverflow.com/questions/2459972

Вопрос

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

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

Затем он использует этот индекс для инициализации большого двумерного массива.Этот массив будет содержать n² записей, где «n» — количество уникальных слов в корпусе текста.Для относительно небольшого фрагмента, на котором я тестирую его (около 60 файлов), необходимо сделать примерно 30 000x30 000 записей.Вероятно, он станет больше, когда я запущу его и на своем полном корпусе.

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

Вещи, которые я сделал, включают в себя:

  • обновите мой код, чтобы использовать примитив int[] вместо TreeMap
  • устранить лишние конструкции и т.д.
  • Кроме того, я запустил программу с-Xmx2g максимально использовать выделенную память

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

Спасибо, Б.

Это было полезно?

Решение

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

Если ты действительно иметь столько записей (ваш текущий массив где-то находится уже более 3 гигабайт, даже при условии отсутствия накладных расходов), то вам придется использовать какое-то дисковое хранилище или систему отложенной загрузки/выгрузки.

Другие советы

Существует несколько причин проблем с нехваткой памяти.

Во-первых, самый простой случай: вам просто нужно больше кучи.Вы используете максимальную кучу 512M, когда ваша программа может корректно работать с 2G.Увеличение происходит с -Xmx2048m как вариант JVM, и все в порядке.Также имейте в виду, что 64-битные виртуальные машины будут использовать в два раза больше памяти, чем 32-битные виртуальные машины, в зависимости от состава этих данных.

Если ваша проблема не так проста, вы можете посмотреть оптимизацию.Замена объектов примитивами и так далее.Это может быть вариант.Я не могу точно сказать, основываясь на том, что вы опубликовали.

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

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

Разделение распределяет ваши данные по нескольким серверам (реальным или виртуальным).Например, если вы отслеживаете сделки с акциями на NASDAQ, вы можете указать коды акций, начинающиеся с «A» на сервере 1, «B» на сервере 2 и т. д.Вам необходимо найти разумный подход к разделению ваших данных таким образом, чтобы уменьшить или устранить необходимость в перекрестной коммуникации, поскольку именно перекрестная связь ограничивает вашу масштабируемость.

Итак, простой случай: если вы храните 30 000 слов и комбинации слов 30 х 30 000, вы можете разделить его на четыре сервера:

  • А-М х А-М
  • А-М х Н-Я
  • Н-З х А-М
  • Н-З х Н-З

Это всего лишь одна идея.Опять же, сложно что-либо комментировать, не зная подробностей.

Это распространенная проблема, связанная с большими наборами данных.Оптимизировать можно сколько угодно, но памяти никогда не будет хватать (вероятно), и как только датасет еще немного вырастет, ты все равно накуришься.Наиболее масштабируемое решение — просто хранить меньше памяти, работать с частями и сохранять структуру на диске (база данных/файл).

Если вам не нужны полные 32 бита (размер целого числа) для каждого значения в вашем 2D-массиве, возможно, подойдет меньший тип, например байт?Также вам следует выделить как можно больше места в куче — 2 ГБ все еще относительно мало для современной системы.Оперативная память дешева, особенно если вы ожидаете, что в памяти будет выполняться большая обработка данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top