Я работал с моим проектом на некоторое время, которое в некоторых точках вычисляет Гистограмма большого изображения (Работа с фотографиями до 40Mpx, но в целом около 10-20Mpx.«outOfMemoryError java heap space» вычислительная гистограмма, торговля оперативной памятью и временем?
Я всегда с использованием ноутбук с 16 ГБ оперативной памяти, и я не заметил никаких проблем. Сегодня я переключился на ноутбук с 6 ГБ и с фотографиями 17Mpx это исключение начало появляться, когда я вычислял гистограмму.
Я переключился на этот способ вычисления потому что это было быстрее, чем повторение всех пикселей и получение всех цветов в каждом пикселе.
Каков ваш совет относительно того, как я должен писать такие код?
Если я ищу, чтобы сделать программу быстрее, я думаю, мне нужно использовать больше ОЗУ (этот большой двойной объект []). Если на ПК достаточно ОЗУ, проблем не будет, и программа будет работать бесперебойно, но если на ПК нет такой большой памяти, она просто сработает и сделает программу бесполезной.
Так должен ли я писать код «медленнее», итерации по всем пикселам вручную и сделать его «безопаснее»?
Или я делаю что-то неправильно, и обе вещи могут быть выполнены одновременно?
Это кусок кода, были это OutOfMemoryError происходит:
// dataset
dataset = new HistogramDataset();
final int w = image.getWidth();
final int h = image.getHeight();
double[] r = new double[w * h]; //Here some PC's with not enough RAM will crash
double[] s = new double[w * h];
double[] t;
r = raster.getSamples(0, 0, w, h, 0, r);
s = r;
dataset.addSeries(lang.getString("HistogramRGB.String.red"), r, BINS);
r = raster.getSamples(0, 0, w, h, 1, r);
t = new double[r.length + s.length]; //Add R+G
System.arraycopy(s, 0, t, 0, s.length);
System.arraycopy(r, 0, t, s.length, r.length);
dataset.addSeries(lang.getString("HistogramRGB.String.green"), r, BINS);
r = raster.getSamples(0, 0, w, h, 2, r);
s = new double[r.length + t.length]; //Add R+G+B
System.arraycopy(t, 0, s, 0, t.length);
System.arraycopy(r, 0, s, t.length, r.length);
dataset.addSeries(lang.getString("HistogramRGB.String.blue"), r, BINS);
dataset.addSeries(lang.getString("HistogramRGB.String.brigthness"), s, BINS);
// chart
chart = ChartFactory.createHistogram(lang.getString("HistogramRGB.String.histogram"), "",
"", dataset, PlotOrientation.VERTICAL, false, true, false);
Update: Использование опции -Xmx предложенный в комментариях решает эту проблему.
Результаты с использованием оптимизации @TheConstructor, в виртуальной машине с помощью окна 10 32bits и 3,5GB барана:
- До оптимизации с менее чем -Xmx1444m будет работать исключение
- После оптимизации с менее чем -Xmx824m запустит исключение
Это то, что у меня есть по умолчанию:
java -XX:+PrintFlagsFinal -version | findstr HeapSize
uintx ErgoHeapSizeLimit = 0 {product}
uintx HeapSizePerGCThread = 67108864 {product}
uintx InitialHeapSize := 16777216 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 268435456 {product}
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) Client VM (build 25.111-b14, mixed mode, sharing)
Это около 268 МБ, и максимум, который я могу установить по команде на этом компьютере, составляет 1,5 ГБ. Мне кажется странным, что без каких-либо других открытий все окна с любой другой программой требуют 2 ГБ 3,5 ГБ.
Быстрый ответ: увеличить память, используемую вашей программой, однако она не позволяет оптимизировать алгоритм. Для этого вы можете попробовать: -Xms1024m (вы должны проверить, сколько RAM ваш JDK позволяет, в общем, зависит от версии сервера или клиента), а затем -XX: MaxPermSize = 128m. Здесь вы являетесь объяснением параметров: https://blog4jose.wordpress.com/2009/02/02/memory-permgen-classloader/ – sirandy
Вы указали опцию '-Xmx' JVM? Если нет, попробуйте это первым. – Andreas