【发布时间】:2017-03-28 16:30:45
【问题描述】:
我一直在使用我的项目一段时间,该项目有时会计算大图像的直方图(使用高达 40Mpx 的照片,但通常在 10-20Mpx 左右。
我一直使用 16GB RAM 的笔记本电脑,但没有发现任何问题。今天我换了一台 6GB 内存的笔记本电脑,当我计算直方图时,有了 17Mpx 的照片,这个异常开始出现。
我改用这种计算方式是因为它比遍历所有像素并获取每个像素中的所有颜色要快。
您对我应该如何编写这样的代码有什么建议?
如果我想让程序更快,我想我需要使用更多的 RAM(这个大的 double[] 对象)。如果 PC 有足够的 RAM,则不会有任何问题,并且程序将运行顺利,但如果 PC 没有这么多 RAM,它只会崩溃并使程序无用。
那么我应该通过手动迭代所有像素以“更慢”的方式编写代码并使其“更安全”吗?
还是我做错了什么,两件事可以同时做?
这是发生 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);
更新: 使用 cmets 中建议的选项 -Xmx 可以解决问题。
使用 @TheConstructor 优化的结果,在使用 windows 10 32 位和 3,5GB ram 的虚拟机中:
- 优化前小于 -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)
大约是 268MB,我可以通过这台计算机中的命令设置的最大值为 1.5GB。我觉得奇怪的是,没有任何其他程序打开整个窗口需要 3.5GB 中的 2GB。
【问题讨论】:
-
一个快速的答案是:增加程序使用的内存,但这并不能解决您的算法优化问题。要运行它,您可以尝试:-Xms1024m(您必须检查 JDK 允许多少 RAM,通常取决于服务器或客户端版本),然后是 -XX:MaxPermSize=128m。这里是对参数的解释:blog4jose.wordpress.com/2009/02/02/memory-permgen-classloader
-
您是否指定了
-XmxJVM 选项?如果没有,请先尝试。
标签: java performance swing out-of-memory histogram