Как оценить, будет ли у данной задачи достаточно памяти для запуска в Java - PullRequest
0 голосов
/ 22 февраля 2012

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

Стало очевидным, что размеры массива около 20 000 000 приводят к «нехватке памяти».ошибка.Поскольку я вызываю это с помощью рефлексии, на самом деле я ничего не могу с этим поделать.

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

Если нет, есть ли лучшие решения?

Вариант использования:

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

  • Мы записываем время, которое требуетсязапустить и измерить значения (для того, чтобы выработать o-нотацию).

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

1 Ответ

1 голос
/ 22 февраля 2012

Вы можете использовать результат Runtime.freeMemory(), чтобы оценить объем доступной памяти. Однако может случиться так, что на самом деле много памяти занято недостижимыми объектами, которые скоро будут возвращены GC. Таким образом, вы можете использовать больше памяти, чем это. Вы можете попытаться вызвать GC раньше, но это не гарантирует ничего.

Вторая сложность заключается в оценке объема памяти, необходимого для числа, заданного пользователем. Хотя с таким количеством записей легко вычислить размер ArrayList, это может быть не все. Например, какие объекты хранятся в этом списке? Я ожидаю, что в каждой записи есть хотя бы один объект, поэтому вам нужно добавить и эту память. Вычислить размер произвольного Java-объекта гораздо сложнее (и на практике это возможно только в том случае, если вы знаете структуры данных и алгоритмы, лежащие в основе этих объектов). И затем во время выполнения алгоритма может быть создано много временных объектов (например, примитивы в штучной упаковке, итераторы, StringBuilders и т. Д.).

В-третьих, даже если доступной памяти теоретически достаточно для выполнения данной задачи, ее может быть практически недостаточно. Java-программы могут работать очень медленно, если куча неоднократно заполняется объектами, затем некоторые из них освобождаются, некоторые новые создаются и т. Д. Из-за большого количества сборщиков мусора.

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

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

Однако учтите, что это не гарантия. Например, если у вас несколько потоков, работающих и занимающих память параллельно, другие потоки могут также получить ошибку OutOfMemoryError и не справиться с этим. Также алгоритм должен поддерживать тот факт, что он может быть прерван в любой произвольной точке. Поэтому следует убедиться, что все необходимые действия по очистке выполняются (и, конечно, у вас проблемы, если им требуется много памяти!).

...