Hoher Speicherverbrauch beim Zeichnen von Images aus einer ArrayList

JTryn

Mitglied
Hallo,

der Titel beschreibt mein Problem eigentlich schon recht präzise.
Mein ganzes Programm wird extrem langsam, wenn erst mehrere Images gezeichnet werden.

Ich erstelle folgendermaßen eine BufferedImage ArrayList, die die Images beinhaltet:
Codeausschnitt:
Java:
ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
Die Images werden ganz normal mit images.add() dann hinzugefügt.

Das Zeichnen funktioniert dann folgendermaßen:
Java:
for(int x=0;x < map.length ;x++){
	for(int y=0; y < map[0].length;y++){			
			g.drawImage(images.get(map[x][y][0]), x*32, y*32 this);				
	}
}

"map" ist einfach nur eine int-Matrix, die dann zum Beispiel '0' enthält, was das Tile bezeichnet,
das an 1. Stelle in "images" geladen wurde.

Jedenfalls funktioniert das ganze nur extrem langsam. Woran liegt das und wie könnte ich es
beheben?

Grüße, JTryn
 
G

Gast2

Gast
Von wievielen Images sprechen wir denn hier?
Was ist map? Was macht images.get(map[x][y][0]) (ist images ne map)?
Wie hoch ist dein Speicherverbrauch?
 

JTryn

Mitglied
Es handelt sich um etwa ~30 Images, also nichts besonders hohes.
map ist wie gesagt einfach nur eine int-Matrix, die beispielsweise Dimensionen von 25,
die mit "0" gefüllt sind.
Die map baut sich von oben links auf, map[0][0][0] ist dann beispielsweise die obere linke Ecke
der Karte. Dort steht dann irgendein int-Wert, beispielsweise 0.
mit images.get(map[0][0][0]) wird dann der int-Wert an dieser Stelle (0) in der ArrayList abgefragt.
0 in der images-ArrayList ist dann irgendeine Grafik, die angezeigt wird.
Das klappt auch alles super, es werden die richtigen Grafiken angezeigt, nur ist der Speicherverbrauch
sehr hoch, was bei dem, was hier gemacht wird, eigentlich nicht der Fall sein darf.
Dabei spreche ich von ~120.000kb, wenn 25*25 Grafiken (die 32x32 Pixel groß sind) angezeigt
werden - das ist einfach viel zu viel. Bevor die Grafiken angezeigt werden beläuft es sich auf ca.
32.000kb, also das Problem taucht wirklich erst beim Anzeigen auf.

Danke schon einmal für die Antwort :) Hoffe es ist dieses mal verständlich.
 

Marco13

Top Contributor
Wenn du den Speicherverbrauch im Taskmanager anschaust: Der hat nicht viel Aussagekraft. Java nimmt sich (bis zur angegebenen Obergrenze) den Speicher, den es braucht, und gibt ihn erst wieder frei, wenn er für andere Sachen gebraucht wird. Solange keine OutOfMemoryException kommt, ist alles OK. Ggf. auch mal im Profiler anschauen (jVisualVM reicht vielleicht schon)
 

JTryn

Mitglied
Ja, ich sehe im TaskManager nach. Gut zu wissen, dass Java so arbeitet :) war mir vorher nicht
bewusst. Allerdings bin ich mir sicher, dass hier etwas falsch abläuft, da es sich hier
um den Ausschnitt eines Map Editors handelt. Die Grafiken werden per Maus gesetzt
(MausX-Koordinate in der Karte geteilt durch die Grafikgröße, das selbe für Y und an dieser Stelle
in der Map-Matrix wird dann die ID der ausgewählten Grafik gesetzt).
Je mehr Grafiken ich habe, desto unflüssiger wird das ganze und der Speicherverbrauch höher.

Ist an meiner Vorgehensweise wirklich nichts falsch? Dann kann der Fehler ja nur irgendwo anders
liegen. Mir kommt's so vor, dass performancebedingte Sachen schwer zu beheben sind, wie
könnte ich denn dahinterkommen woran es liegt?
 

Marco13

Top Contributor
An dem Geposteten ist nichts falsch (da gab es auch nicht viel, was hätte falsch sein können - etwas mehr Code würde vielleicht mehr Aufschluss bringen). Wie lädst du denn die Bilder? Sind das vielleicht PNGs mit Transparenz drin?
 

JTryn

Mitglied
So, ich habe das ganze mal stark abgespeckt.

Fenster (hiervon wird in der Main-Methode ein Objekt erzeugt, dass das ganze einleitet.)
Java:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class MapWindow extends JFrame {
	
	private static final long serialVersionUID = 1L;

	Map currentMap;
	MapView view;

	public MapWindow(){
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.requestFocus();

		String tilesetFilename = "Tileset.png";
	
		currentMap = new Map(30, 20, tilesetFilename);
		view = new MapView(currentMap, this);

		for(int x=0;x<currentMap.map.length;x++){
			for(int y=0;y<currentMap.map[0].length; y++){
				currentMap.map[x][y][0] = -1;
				currentMap.map[x][y][1] = -1;
				currentMap.map[x][y][2] = -1;
			}
		}
		
		add(view.scroll, BorderLayout.CENTER);

		setSize(1024, 768);
		setTitle("Map Editor");
		
	}
}

Hier werden die Images in die ArrayList geladen und die Matrix erstellt:
(Dass die zwei Dinge in einer Klasse sind ist wohl unpassend, aber jetzt bitte einfach davon
absehen.)
Java:
public class Map {
	String mapName;
	String tilesetFilename;
	int maplayers = 3;
	int[][][] map = new int[0][0][0];
	
	ArrayList<BufferedImage> tileset = new ArrayList<BufferedImage>();
	
	public Map(int mapwidth, int mapheight, String filename){
		
		this.tilesetFilename=filename;
		map = new int[mapwidth][mapheight][maplayers];

		try {
			BufferedImage picTileset=ImageIO.read(new File(filename));
			this.tileset.add(picTileset.getSubimage(0, 0, 32, 32));
			this.tileset.add(picTileset.getSubimage(0, 32, 32, 32));
		}catch (IOException error){
			System.err.println("Tileset "+filename+" not found.");
			error.printStackTrace();
		}
	}
	
	public void setTile(int x, int y, int z, int tileID){
		map[x][y][z]=tileID;
	}
}

Und die Klasse, die es anzeigt.

Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MapView extends JPanel { 

	private static final long serialVersionUID = 1L;
	
	MapWindow window;
	Map map;
	
	JScrollPane scroll=new JScrollPane();
	
	JViewport viewport;
	RepaintManager m;
	     
	public MapView(Map map, MapWindow mwindow){
		scroll.setViewportView(this);
		window=mwindow;
		setDoubleBuffered(true);
		m = RepaintManager.currentManager(window);
		this.viewport = scroll.getViewport();
		
		addMouseListener(new MouseAdapter()
		{
			@Override
			public void mousePressed(MouseEvent e){
				int keyCode = e.getButton();
				if (e.getX()<window.currentMap.map.length*32 && e.getY()<window.currentMap.map[0].length*32){
					if (keyCode == MouseEvent.BUTTON1){
						drawTile(e.getX(), e.getY(), 0);
					}else if(keyCode == MouseEvent.BUTTON3){
						deleteTile(e.getX(), e.getY(), 0);
					}
				}
			}			
		});
		
		addMouseMotionListener(new MouseMotionAdapter()
		{
			@Override
			public void mouseDragged(MouseEvent e){
				if (e.getX()<window.currentMap.map.length*32 && e.getY()<window.currentMap.map[0].length*32){
					if (SwingUtilities.isLeftMouseButton(e)){
						drawTile(e.getX(), e.getY(), 0);
					}else if(SwingUtilities.isRightMouseButton(e)){
						deleteTile(e.getX(), e.getY(), 0);
					}
				}
			}		
		});
	}
 
	public void paintComponent(Graphics g){
		
		this.viewport = scroll.getViewport();
		
		g.setColor(Color.white);
		g.fillRect(0,0, window.currentMap.map.length*32, window.currentMap.map[0].length*32);
		
		for(int x=0;x < window.currentMap.map.length;x++){
			for(int y=0; y < window.currentMap.map[0].length;y++){
					if(window.currentMap.map[x][y][0] != -1){
						g.drawImage(window.currentMap.tileset.get(window.currentMap.map[x][y][0]), x*32, y*32, this);
					}					
			}
		}
		
		g.setColor(Color.gray);
		for(int i=0; i<window.currentMap.map.length; i++)
		{
			g.drawLine(i*32, 0, i*32, window.currentMap.map[0].length*32);
		}
		for(int j=0; j<window.currentMap.map[0].length; j++)
		{
			g.drawLine(0,j*32, window.currentMap.map.length*32, j*32);
		}
		
		((Graphics2D)g).setStroke(new BasicStroke(2));
		g.setColor(Color.black);
		g.drawLine(0, 0, window.currentMap.map.length * 32, 0);
		g.drawLine(0, 0, 0, window.currentMap.map[0].length * 32);
		g.drawLine(window.currentMap.map.length * 32, 0, window.currentMap.map.length * 32, window.currentMap.map[0].length * 32);
		g.drawLine(0, window.currentMap.map[0].length * 32, window.currentMap.map.length * 32, window.currentMap.map[0].length * 32);
			
	}
		
	public void drawTile(int x, int y, int z){
		x /= 32;
		y /= 32;
		window.currentMap.map[x][y][z] = 0;
			
		Rectangle r=scroll.getViewport().getViewRect();
		int dx=this.scroll.getLocation().x+window.getInsets().left-r.x;
		int dy=this.scroll.getLocation().y+window.getInsets().top-r.y;
		m.addDirtyRegion(window , dx+1+x*32, dy+2+y*32, 32, 32);
		
		System.out.println("Set tile at: "+x+" "+y+" "+z);
	}
	
	public void deleteTile(int x, int y, int z){
		x /= 32;
		y /= 32;
		window.currentMap.map[x][y][z] = -1;
		
		Rectangle r=scroll.getViewport().getViewRect();
		int dx=this.scroll.getLocation().x+window.getInsets().left-r.x;
		int dy=this.scroll.getLocation().y+window.getInsets().top-r.y;
		m.addDirtyRegion(window , dx+1+x*32, dy+2+y*32, 32, 32);

	}
	
}

Sollte sogar aufrufbar sein (falls nötig), als Grafik einfach ein mindestens 64x32 Pixel großes Bild nehmen
und oben bei Tileset.png eben anpassen.
Hier sieht man dann, dass es langsamer wird je mehr man reinmacht und schneller, wenn man die
Grafiken wieder entfernt.
 
Zuletzt bearbeitet:

JTryn

Mitglied
Ja, daran liegt es, vielen Dank!

Allerdings frage ich mich warum dieses Problem am PC eines Bekannten gar nicht erst auftaucht
und er unabhängig davon ob er die Lösung verwendet oder nicht den selben Speicherverbrauch
hat.
 

Marco13

Top Contributor
Das mit dem Speicher hat damit ja nichts zu tun... und wenn es auf dem anderen PC schneller läuft, könnte das zum Beispiel daran liegen, dass der PC (bzw. die Grafikkarte) schneller ist ;)
 

JTryn

Mitglied
Daran habe ich natürlich auch schon gedacht, aber das ist noch nicht mal der Fall,
deswegen verwundert mich es so. Der Unterschied zwischen den Systemen ist,
dass ich eine Geforce 9600 und er eine Geforce 7600 hat. Der Prozessor ist
genauso 'noch' ein DualCore wie meiner und auch nur leicht besser.
Vom System her ist es bei ihm WinXP und bei mir Win7, der einzige markante
Unterschied ist, dass er, wenn ich mich recht entsinne, 2GB mehr RAM hat.

Aber gut, mit der Lösung kann ich ja praktisch nichts falsch machen :).
Danke noch einmal!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G JLabel wir auf Grund zu hoher Rechenlast oft nicht angezeigt Java Basics - Anfänger-Themen 9
K StringBuilder Objekt überschreiben - Speicherverbrauch Java Basics - Anfänger-Themen 3
J Arrays erweitern - Performance vs Speicherverbrauch Java Basics - Anfänger-Themen 6
M Speicherverbrauch von Objekt ermitteln Java Basics - Anfänger-Themen 3
S Frage zu Speicherverbrauch Java Basics - Anfänger-Themen 5
Juelin jedit Fehler beim starten Java Basics - Anfänger-Themen 2
Kerstininer Vererbung Hilfe beim lernen von Objektorientierung für eine Klausur Java Basics - Anfänger-Themen 10
A Hilfe beim Lesen von Pfaden und Systemvariablen Java Basics - Anfänger-Themen 3
M Ausgabe beim Overloading Java Basics - Anfänger-Themen 3
W Null-Pointer Exception beim Programmstart Java Basics - Anfänger-Themen 8
H Nutzt Eclipse alle CPU-Threads beim Ausführen von Java-Programmen? Java Basics - Anfänger-Themen 4
M Nullpointer beim befüllen meiner Liste im Object Java Basics - Anfänger-Themen 3
J Beim Start des Programms zB. eine Linie in JPanel ausgeben Java Basics - Anfänger-Themen 4
I Projekte in IDE untereinander sharen / Probleme beim Build Java Basics - Anfänger-Themen 8
paulen1 Best Practice "Unchecked Assignment" Warnung beim erstellen eines 2D Arrays of Arraylists Java Basics - Anfänger-Themen 2
T Probleme beim Import eines Git-Repos Java Basics - Anfänger-Themen 2
C GLOOP Problem beim Erstellen der Kamera Java Basics - Anfänger-Themen 9
N Array beim erstellen mit Werten füllen Java Basics - Anfänger-Themen 6
T DamagedFontException beim drucken Java Basics - Anfänger-Themen 3
Z SNAKE Schlange beim Aufheben von Essen verlängern Java Basics - Anfänger-Themen 4
Bugs Bunny Fehlerhafte Berechnung beim erneuten Durchlaufen der Schleife Java Basics - Anfänger-Themen 5
stormyark Fehler beim überschreiben einer Variable Java Basics - Anfänger-Themen 1
T String Array Fehler beim Index Java Basics - Anfänger-Themen 3
Fiedelbambu Prüfen von Komma stelle beim Taschenrechner Java Basics - Anfänger-Themen 5
B Objekte verschwinden beim Übersetzen Java Basics - Anfänger-Themen 5
L Beim Java Programmstart, mehrere Parameter über die Kommandozeile übergeben Java Basics - Anfänger-Themen 9
sserio Problem beim Anzeigen Java Basics - Anfänger-Themen 5
X Hilfe beim Übertragen in eine For-Schleife Java Basics - Anfänger-Themen 1
S Fehler beim Programm Java Basics - Anfänger-Themen 2
G Main Methode wird beim ersten Aufruf nicht richtig ausgeführt Java Basics - Anfänger-Themen 1
M String beim einlesen formatieren Java Basics - Anfänger-Themen 12
N Exception beim Verwenden von Arraylist? Java Basics - Anfänger-Themen 10
I InputStream beim zweiten Mal fehlerhaft Java Basics - Anfänger-Themen 10
C Fehler beim erstellen eines Objektes Java Basics - Anfänger-Themen 3
C Brauche Hilfe beim Schreiben eines Programmes :/ Java Basics - Anfänger-Themen 1
cmn489 Werte beim Funktionsaufruf in ein Feld übertragen(falls dieses leer ist) Java Basics - Anfänger-Themen 1
I Output BigDecimal anstatt double / Problem beim Rechnen Java Basics - Anfänger-Themen 16
S Kriege Fehler "Exception in thread" beim Benutzen von SubStrings. Java Basics - Anfänger-Themen 2
D Hilfe beim Erzeugen eines Arrays NullPointerException wird ausgelöst Java Basics - Anfänger-Themen 11
Nerdinfekt BMI Rechner, fehler beim Zurückgeben des Strings? Java Basics - Anfänger-Themen 2
CptK Richtigen Pfad beim einlesen von Datei finden Java Basics - Anfänger-Themen 2
O Methode in while-Schleife aufrufen geht nur beim ersten Mal Java Basics - Anfänger-Themen 2
pry bitte Hilfe beim Kreditrechner objektorientiert Java Basics - Anfänger-Themen 6
J Hilfe beim Label animieren Java Basics - Anfänger-Themen 1
Avalon Programmierstil beim Mocken Java Basics - Anfänger-Themen 45
Avalon NullPointerException beim Mocken Java Basics - Anfänger-Themen 6
J Hilfe beim verstehen Java Basics - Anfänger-Themen 3
A Fehler beim Ausführen einer class Datei Java Basics - Anfänger-Themen 6
P Problem beim Überschreiben einer vererbten Methode Java Basics - Anfänger-Themen 4
M Compiler-Fehler Fehler beim Ausführen des Codes Java Basics - Anfänger-Themen 25
L Anfänger braucht Hilfe - Stecke beim Lernen fest Java Basics - Anfänger-Themen 10
N Probleme beim printen von Arrays durch for Schleife Java Basics - Anfänger-Themen 3
Bluedaishi Hilfe beim erklären dieser Methode Java Basics - Anfänger-Themen 5
E Macht Java Rechenfehler beim Potenzieren und Mod? Java Basics - Anfänger-Themen 5
J Hilfe beim Programmieren Java Basics - Anfänger-Themen 5
C Fehler beim Speichern (Build projekt) Java Basics - Anfänger-Themen 42
S Endlosschleife beim Ausgeben einer LinkedList Java Basics - Anfänger-Themen 2
tom.j85 TicTacToe - probleme beim Casten Java Basics - Anfänger-Themen 6
J Problem beim vergleich von zwei Integer Java Basics - Anfänger-Themen 3
Kirby.exe Fehler beim Ausgeben Java Basics - Anfänger-Themen 2
L Brauche Hilfe beim arbeiten mit Konstruktoren Java Basics - Anfänger-Themen 20
D Was tun gegen zu komplzierten Denken beim Programmieren Java Basics - Anfänger-Themen 27
G Problem beim Speichern von Objekten in einer Datei Java Basics - Anfänger-Themen 7
S Collections funktionale Listen (ListNode<E>) review und problem beim clone Java Basics - Anfänger-Themen 0
J NullPointerException beim Klonnen eines Arayys und beim aufrufen einer Methode Java Basics - Anfänger-Themen 2
J Fehler beim generieren von 4 Zufallszahlen Zahl doppelt ist eigentlich ausgeschlossen Java Basics - Anfänger-Themen 9
L Kleine Hilfe beim Schreiben eines Programmes benötigt :D Java Basics - Anfänger-Themen 40
T Fehlermeldung beim Versuch, einen String einzulesen Java Basics - Anfänger-Themen 4
V Wie wiederhole ich eine for-Schleife beim erreichen eines Wertes Java Basics - Anfänger-Themen 9
W Hilfe beim Chat Programm Java Basics - Anfänger-Themen 14
D Beim Programmieren auf die Logisch einfache Lösung kommen. Java Basics - Anfänger-Themen 17
S IndexOutOfBoundsException beim hinzufügen eines Elements zu einer Liste Java Basics - Anfänger-Themen 11
R String index out of range: -1 beim Datei Parsen Java Basics - Anfänger-Themen 15
I Methoden List.contains() beim 2. Element = true Java Basics - Anfänger-Themen 1
B EJB und Arquillian - bekomme Nullpointer Exception beim Aufruf der EJB Klasse Java Basics - Anfänger-Themen 40
O Verwirrt beim Java Collection Framework aufruf! Java Basics - Anfänger-Themen 9
S switch case fängt beim letzten case an Java Basics - Anfänger-Themen 6
S Erste Schritte Hilfe beim lernen von Programmieren Java Basics - Anfänger-Themen 2
der_Schokomuffin Hilfe gesucht beim Thema Objekte übergeben! Java Basics - Anfänger-Themen 2
A Pendeltouren beim Savings erfahren "schummeln" in Ordnung? Java Basics - Anfänger-Themen 1
dapzoo Compiler-Fehler Beim Werte verteilen in Objektarray NullPointerException Java Basics - Anfänger-Themen 4
C Methoden Problem beim Speichern von Variablen Java Basics - Anfänger-Themen 1
T Fehlermeldung beim Starten von FlashTool Java Basics - Anfänger-Themen 27
C Rekursives Backtracking beim Spiel Peg Java Basics - Anfänger-Themen 22
K Fehler beim Programmieren von TicTacToe Java Basics - Anfänger-Themen 12
J Hilfe beim Runden Java Basics - Anfänger-Themen 4
C Erste Schritte ArrayIndexOutOfBoundsException beim Speichern im Array Java Basics - Anfänger-Themen 2
F Problem beim entfernen von mehreren Listenelementen auf einmal (Programmierung des Spiels Arschloch) Java Basics - Anfänger-Themen 1
L Fehler beim laden eines Icons Java Basics - Anfänger-Themen 3
D Probleme beim Kompelieren mache ich etwas falsch ? Java Basics - Anfänger-Themen 3
R Methoden NPE beim Aufruf einer Methode einer anderen Klasse Java Basics - Anfänger-Themen 4
K Probleme beim Programm schreiben - Lesen von Dateiinhalten -zaehlen von Wörtern/ Buchstaben Java Basics - Anfänger-Themen 4
M Probleme beim aktualisieren eines JPanels Java Basics - Anfänger-Themen 7
J Probleme beim Array ausgeben Java Basics - Anfänger-Themen 4
CptK Bild beim betätigen eines JButtons Java Basics - Anfänger-Themen 6
D Könnt ihr mir helfen beim Programmieren eines Ping Pong Spieles? Java Basics - Anfänger-Themen 9
N Fehlermeldung beim ausführen des Programmes.. Java Basics - Anfänger-Themen 3
K Classpath RXTX beim Raspberry Java Basics - Anfänger-Themen 5
F (Eclipse) Beim importieren etwas fehlerhaft bitte um Hilfe :) Java Basics - Anfänger-Themen 3
B Datentypen Welcher Typ wird beim Casten übernommen? Java Basics - Anfänger-Themen 12

Ähnliche Java Themen

Neue Themen


Oben