I've been working with my project for a while which at some points calculates the Histogram of a big image (Working with photos of up to 40Mpx, but in general around 10-20Mpx.
I was always using a laptop with 16GB of RAM and I had not noticed any problem. Today I switched to a 6GB ram laptop and with photos of 17Mpx this Exception started to appear when I was calculating an Histogram.
I had switched to this way of calculating it because It was faster than iterating over all pixels and getting all the colors in each pixel.
What is your advice on how should I write such a code?
If I'm looking to make the program faster I think I need to use more RAM (this big double[] object). If the PC has enough RAM there won't be any problem and the program will run smooth, but if the PC doesn't have this much RAM it will just crash and make the program useless.
So should I write the code in a "slower way" by iterating over all pixels by hand and make it "safer"?
Or am I doing something wrong and both things can be done at the same time?
This is the piece of code were this outOfMemoryError occurs:
// 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: Using the option -Xmx suggested in the comments solves the problem.
Results using @TheConstructor optimization, in a virtual machine using windows 10 32bits and 3,5GB ram:
- Before the optimization with less than -Xmx1444m will run the exception
- After the optimization with less than -Xmx824m will run the exception
This is what I have by default:
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)
Which is around 268MB, and the maximum I can set by the command in this computer is 1,5GB. I find it strange that without anything else opened the whole windows with any other program requires 2GB of the 3.5GB.