Witam wszystkich forumowiczów,
Załączam kod testowej klasy, która jest wycinkiem mojego programu do przetwarzania obrazów.
Problem mam taki, że wczytuję tam wielokrotnie duże ilości obrazów, czasem np. ok. 300. Każdy ma rozdzielczość 512x512px;
Każdy piksel obrazu opisuję klasą Point. Tak więc dla każdego obrazu tworzę 512x512 obiektów typu Point, które przechowuję w tablicy Point[][].
Następnie każdy z tych obrazów przechowuję w kolekcji ArrayList<Point[][]>. Czyli kolekcja zawierać może ok. 300 takich tablic.
W przesłanej klasie imituję zachowanie mojego programu podczas wczytywania danych.
W klasie Test jest zmienna 'count', która mówi o ilości "obrazów".
Przy małej liczbie (<100) wszystko jakoś działa, ale przy większej liczbie zawsze wywali Java Heap Space przy ogólnej liczbie pamięci ponad 1GB!
Oto mój testowy kod:
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Scanner;
public class ObjectPerformanceTest {
public static void main(String[] args) {
Test test = new Test();
}
}
class Test {
public Test() {
int count = 20; //INCREASE THIS VALUE (e.g. 200) AND OBSERVE MEMORY USAGE
test1(count);
System.out.println("-------------");
test2(count);
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
}
private void test1(int count) {
float time = 0.0F;
time = performCreateByNewTest(count);
System.out.println("New object consuming: " + time + " sec");
displayMemory();
}
private void test2(int count) {
try {
float time = 0.0F;
time = performCreateByCloneTest(count);
System.out.println("Clone object consuming: " + time + " sec");
displayMemory();
} catch (CloneNotSupportedException e) {
}
}
private float performCreateByNewTest(int count) {
long start = System.currentTimeMillis();
ArrayList<Point[][]> pointsArr = new ArrayList<Point[][]>();
for (int c = 0; c < count; c++) {
Point[][] points = new Point[512][512];
for (int i = 0; i < 512; i++)
for (int j = 0; j < 512; j++) {
Point p = new Point(i, j);
p.setIntensity(1000);
points[i][j] = p;
}
pointsArr.add(points);
}
long elapsedTimeMillis = System.currentTimeMillis()-start;
return elapsedTimeMillis/1000F;
}
private float performCreateByCloneTest(int count) throws CloneNotSupportedException {
long start = System.currentTimeMillis();
ArrayList<Point[][]> pointsArr = new ArrayList<Point[][]>();
for (int c = 0; c < count; c++) {
Point[][] points = new Point[512][512];
for (int i = 0; i < 512; i++)
for (int j = 0; j < 512; j++) {
Point p = createPointObject();
p.setX(i);
p.setY(j);
p.setIntensity(1000);
points[i][j] = p;
}
pointsArr.add(points);
}
long elapsedTimeMillis = System.currentTimeMillis()-start;
return elapsedTimeMillis/1000F;
}
Hashtable<String, Point> _cacheTemplate = new Hashtable<String, Point>();
public Point createPointObject() throws CloneNotSupportedException {
Point p = (Point) _cacheTemplate.get( "Point" );
if (p == null) {
p = new Point();
_cacheTemplate.put( "Point", p );
}
return (Point) p.clone();
}
public void displayMemory() {
int mb = 1024*1024;
Runtime r = freeMemory();
System.out.println("Total memory: " + (double)r.totalMemory()/mb + " MB");
System.out.println("Free memory: " + (double)r.freeMemory()/mb + " MB");
System.out.println("Memory Used="+(double)(r.totalMemory()-r.freeMemory())/mb + " MB");
}
public Runtime freeMemory() {
Runtime r = Runtime.getRuntime();
r.gc();
r.gc();
return r;
}
}
class Point implements Cloneable, Comparable<Point> {
private int x = 0;
private int y = 0;
private int intensity = 0;
public Point() {}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getIntensity() {
return intensity;
}
public void setIntensity(int intensity) {
this.intensity = intensity;
}
public void increase(int val){
this.intensity = this.intensity + val;
}
@Override
public String toString() {
return "("+x+", "+y+") = "+intensity;
}
public Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
public int compareTo(Point p) {
return this.getIntensity() - p.getIntensity();
}
}
Bardzo proszę o podpowiedzi, jak ten problem rozwiązać.
Będę wdzięczny za wszelkie odpowiedzi.
Pozdrawiam.
Kerai