Warum läuft dieses Programm so langsam?

Status
Nicht offen für weitere Antworten.
D

Doubleslash

Gast
Hallo,

in unserem Programmierpraktikum im Studiengang Wirtschaftsinformatik war neulich die Aufgabe gestellt worden, eine rekursive Methode zu schreiben, die ein gegebenes Feld von Zeichen (in welcher Form auch immer) permutiert, also alle Möglichkeiten der Anordnungen seiner Elemente ausgibt. Ich habe das versucht wie folgt (beachtet, dass von uns verlangt wurde, dass auf Java 1.4 Stufe zu machen, daher keine Verwendung generischer Typen):

Code:
import java.util.LinkedList;
import java.util.List;

/*
 * Knobel-Aufgabe:
 * 
 * Dieses Programm berechnet aus einer gegebenen Liste von Elementen der Groeße
 * n alle n-Fakultaet Permutationen, die sich daraus ergeben. Als Datenstrukturen
 * werden List bzw. LinkedList zur Rueckgabe verwendet.
 */
public class Permutationen
{
	/*
	 * Berechnet zu einer gegebenen Zahl n die Fakultaet und gibt sie zurueck.
	 */
	public static int fakultaet(int n)
	{
		int fakultaet = 1;
		
		for(;n > 1;n--)
		{
			fakultaet *= n;
		}
		
		return fakultaet;
	}
	
	/*
	 * Erstellt zu einer gegebenen List von Elementen eine LinkedList-Array, dessen
	 * LinkedList-Instanzen jeweils eine Permutation (Erhebung) darstellen.
	 * Dabei wird das Prinzip verwendet, dass besagt, dass eine Vollerhebung (n! Permutationen)
	 * eines Feldes daraus zustande kommt, dass man jeweils alle Permutationen des Teilfeldes der Laenge
	 * n-1 bildet und zu jeder dieser Teilerhebungen neue Erhebungen erstellt in denen jeweils das letzte
	 * (nicht in das permutierte Teilfeld einbezogene) Element durch alle moeglichen Stellen der Teilerhebungen
	 * wandert. Pro Teilerhebung der Laenge l(=n-1) entstehen somit l+1(=n) neue Teilerhebungen.
	 * Somit entstehen insgesamt bei (n-1)! Teilerhebungen mal l+1 neue Teilerhebungen, also
	 * (n-1)! * n = n!
	 */
	public static LinkedList[] permutare(List feld)
	{		
		if(feld.size() == 1) // einfachster Fall (Rekursionsende)
		{
			LinkedList vollErhebung = new LinkedList();
			vollErhebung.add(feld.get(0));
			return new LinkedList[] {vollErhebung}; // die Vollerhebung einer 1-stelligen Liste erzeugt eine Permutation, die Liste selbst
		}
		else
		{
			LinkedList[] teilErhebungen = permutare(feld.subList(0, feld.size()-1)); // Teilerhebung der Liste 1 ... n-1 bilden
			
			LinkedList[] vollErhebungen = new LinkedList[fakultaet(feld.size())]; // Array mit LinkedList-Instanzen der Laenge n! vorbereiten
						
			for(int i = 0, v = 0; i < teilErhebungen.length; i++) // das Array aller (n-1)! entstandenen Teilerhebungen iterieren
			{				
				for(int p = 0; p <= teilErhebungen[i].size(); p++, v++) // aktuelle Teilerhebungen als LinkedList iterieren
				{
					teilErhebungen[i].add(p, feld.get(feld.size()-1)); // an aktuelle Teilerhebung in aktuelle Position das n-te Element der gegebenen Liste positionieren
					vollErhebungen[v] = (LinkedList)teilErhebungen[i].clone(); // die daraus neu enstehende Erhebung zum Ergebnis der Vollerhebung kopieren (shallow copy)
					teilErhebungen[i].remove(p); // Teilerhebung wieder in Originalzustand versetzen 
				}
				
				teilErhebungen[i] = null; // GC anweisen, dass Objekt aus dem RAM zu entfernen (Perfomance)
			}
			
			teilErhebungen = null; // -""-
			feld = null; // -""-
			
			return vollErhebungen; // Vollerhebung zurueckgeben
		}
	}
	
	public static void main(String[] args)
	{
		LinkedList list = new LinkedList();
		list.add(list.size(), Integer.valueOf(1));
		list.add(list.size(), Integer.valueOf(2));
		list.add(list.size(), Integer.valueOf(3));
		list.add(list.size(), Integer.valueOf(4));
		list.add(list.size(), Integer.valueOf(5));
		list.add(list.size(), Integer.valueOf(6));
		list.add(list.size(), Integer.valueOf(7));
		list.add(list.size(), Integer.valueOf(8));
//		list.add(list.size(), Integer.valueOf(9)); // funktioniert erst wenn man der JVM mind. 128 MB RAM zuweist
//		list.add(list.size(), Integer.valueOf(10));
//		list.add(list.size(), Integer.valueOf(11));
		
		LinkedList[] vollErhebung = permutare(list);
		
		for(int i = 0; i < vollErhebung.length;i++)
		{
			System.out.println(vollErhebung[i]);
		}
		
		System.out.println("\nDie Liste " + list + " hat " + vollErhebung.length + " Permutationen!");
	}
}

Wie ich schon im Kommentar geschrieben habe, geht das ab 9 Elementen in der Liste nimmer ohne den RAM der JVM zu vergrößern. Das kanns doch aber nich sein. Ich habe an den 3 Stellen im Code mit dem entsprechenden Kommentar schon die Objekte die nur temporär benötigt werden auf "null" gesetzt, damit sie der Garbage Collector rauswirft. Trotzdem tritt ab 9 Elementen in der zu permutierenden Liste ohne RAM-Erweiterung "heap space"-Fehler auf - der JVM geht der Speicher aus. Ich verstehe das nicht. Löscht der GC die Objekte nicht oder liegt es daran, dass eine LinkedList (oder generell eine List) nicht so viele Elementen handhaben kann?

Ich weiß, man hätte das sicher auf mit einem einzigen Array lösen können, aber ich möchte für den Erfahrungswert wissen, wo hier das Perfomance-Problem liegt. Einer von euch ne Idee?
 

André Uhres

Top Contributor
Wenn eine Variable auf null gesetzt wird dann schreitet der GC nicht sofort ein.
Man kann es mit System.gc() versuchen, aber dann dauert es noch länger!
 
B

bygones

Gast
irgendwie ist das glaub ich nicht mein Tag ^^

kannst du mir erklären, dass der Algorithmus korrekt läuft ?

Code:
LinkedList[] teilErhebungen = permutare(feld.subList(0, feld.size()-1));
solange die liste größer ist als ein element, rufst du die Methode erneut auf mit einer liste um eins kleiner. Wenn die Liste ein Element hast steckst du das in eine Liste, die in einen Array kommt....

d.h. bei einer Liste mit 3 Elementen 1,2,3:

1. permutare([1,2,3]) -> else zweig
2. permutare([1,2]) -> else zweig
3. permutare([1]) -> if und in den array und return, rekursion wird unterbrochen

d.h. teilErhebung ist nun ein Array mit einer Liste mit 1 drinnestehen.
Dann machst du weiter.... ich seh jedenfalls hier keine permutation ?!

falscher Algo oder ist deathbyaclown nun blindclown?

btw: beim adden brauchst du nicht immer size() aufrufen, wenn kein parameter ist wird immer hintan angehängt.

Zum GC - der läuft irgendwann ohne dass jemand ihn zwingen kann.... seh gc() als netten Ratschlag :)
 
S

SlaterB

Gast
@deathbyaclown:
ws stört dich denn? bei einem Element ist nicht viel zu tun und es wird einfach eine einelementige Liste zurückgegeben,
die dann aber im nächsten (vorherigen) Schritt sinnvoll weiterverarbeitet (zu einer Liste mit zwei Elementen: [1,2] und [2,1]),
so arbeitet doch eine Rekursion?

@Doubleslash:
viel tun kann man nicht, eine LinkedList mit 10 Elementen braucht nun mal ~240 Bytes,
363.000 Stück davon -> 87 MB,
die entstehen praktisch alle im letzten Arbeitsschritt, die 40.000 von der Teilerhebung machen nur 10% mehr aus,

für die Arrays zur Speicherung der Listen fallen auch noch mal ein paar kleine MB an..

------------

der GC hat da ne Menge zu tun wenn er bei sovielen Objekten aufräumen will ,

ich hab mal irgendwo folgendes aufgeschnappt,:

Code:
	public static void runGC () {
        // It helps to call Runtime.gc()
        // using several method calls:
        try {
        	for (int r = 0; r < 4; ++ r) {
        		_runGC ();
        	}
        } catch(Exception e) {
        	e.printStackTrace();
        }
    }

    public static void _runGC () throws Exception
    {
        long usedMem1 = usedMemory (), usedMem2 = Long.MAX_VALUE;
        for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++ i)
        {
            s_runtime.runFinalization ();
            s_runtime.gc ();
            Thread.yield ();
            
            usedMem2 = usedMem1;
            usedMem1 = usedMemory ();
        }
    }
ein solcher Aufruf (ganz am Ende) sparte bei mir am ein paar MB ein, dauerte aber viele Sekunden Bearbeitungszeit
(x-facher Aufruf vielleicht unnötig ;) ),
mach das bloß nicht öfters im Programm, etwa in jedem Schleifendurchlauf ;)
 
G

Guest

Gast
Danke SlaterB. Also liegts doch an der Verwendung von LinkedList. Das so viele Elemente im letzten Schritt entstehen ist halt zwangsläufig durch dei Rekursion gegeben, wir sollten das ja so machen. Ich dachte nur, ich hätte die Rekursion irgendwie ungünstig implementiert, aber so is ja alles i.O. Mit der Verwendung von reinen Arrays ist es definitiv performanter.

Das mit dem size()-Argument muss ich so machen, da von uns Java 1.4.2-Konfirmität verlangt wurde, daher auch keine generischen Typen etc. Thx nochmal für den Hinweis mit dem Speicherverbrauch. Gibts irgendwo ne Übersicht des konkreten Arbeitsspeicherverbrauchs jeder in Java nativ implementierter Datenstruktur?
 
S

SlaterB

Gast
List.add() ist sicherlich nicht Java 1.5, das gabs schon von Anfang an ;)

---------------

Speicher: zur Not selber messen:
Speichergröße vorher auslesen, Objekte erzeugen und wieder Speicher auslesen


um Abweichungen/ Erstellung von Listen nebenbei auszugleichen evtl. 1000 Objekte auf einmal erstellen
und/ oder den Messvorgang mehrfach hintereinander durchführen

zum Messen des Speichers:
Code:
    private static final Runtime s_runtime = Runtime.getRuntime ();
    private static long memory;

    public static long totalMemory () {
    	return s_runtime.totalMemory ();
    }

    public static long usedMemory () {
        return s_runtime.totalMemory () - s_runtime.freeMemory ();
    }

    public static void initMemory () {
        memory = usedMemory();
    }

    public static long aktMemory() {
        return usedMemory() - memory;
    }
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
A "Hello World"-Programm läuft nicht Java Basics - Anfänger-Themen 16
MoxMorris Einige Methoden aus verschiedenen Klassen nacheinander auszuführen läuft seltsam Java Basics - Anfänger-Themen 2
G Programm läuft durch, ohne Eingabe aus dem Chat abzuwarten Java Basics - Anfänger-Themen 4
N Interpreter-Fehler Compiler zeigt keine Fehler an, aber das Programm läuft nicht (BlueJ) Java Basics - Anfänger-Themen 2
A JavaFX-Anwendung läuft nicht mit Selenium WebDriver Java Basics - Anfänger-Themen 0
K Warum läuft das Programm nicht(bzw. nicht richtig) Java Basics - Anfänger-Themen 4
C Java boolean Code läuft nicht Java Basics - Anfänger-Themen 5
R CSV Reader läuft nicht richtig an Java Basics - Anfänger-Themen 8
J Mein Programm läuft bei der ersten Eingabe nicht mehr weiter, woran liegt das? Java Basics - Anfänger-Themen 6
SpigBin Programm läuft nicht weiter... Java Basics - Anfänger-Themen 10
OSchriever Jar-Programm läuft auf Windows aber nicht auf Linux(Raspberri Pi4) Java Basics - Anfänger-Themen 22
V Anfängerfrage: HelloWorld läuft nicht Java Basics - Anfänger-Themen 3
C java.util Timer läuft zu langsam? Java Basics - Anfänger-Themen 1
Zrebna Programm kann aus der Konsole nicht gestartet werden (in der IDE läuft es) Java Basics - Anfänger-Themen 2
A Java-Programm läuft bei installierter JDK aber nicht mit JRE? Java Basics - Anfänger-Themen 5
B OOP While Schleife läuft Endlos durch externen aufruf Java Basics - Anfänger-Themen 2
W Warum läuft mein Programm nicht? Java Basics - Anfänger-Themen 14
D Erste Schritte Java läuft nicht Java Basics - Anfänger-Themen 33
M Erste Schritte while boolean=false läuft nur bei true??? Java Basics - Anfänger-Themen 23
S Programm läuft nicht weiter, wie Code wiederholen? Java Basics - Anfänger-Themen 2
C Threads SwingWorker läuft trotz cancel weiter Java Basics - Anfänger-Themen 22
D Programm läuft plötzlich nicht weiter Java Basics - Anfänger-Themen 12
S Input/Output Programm läuft nach input-Abfrage nicht weiter. Java Basics - Anfänger-Themen 2
L do-while-Schleife läuft doppelt, try catch fehler Java Basics - Anfänger-Themen 12
J ireport Designer / CSV / Sonderzeichen was läuft falsch Java Basics - Anfänger-Themen 7
M Simpler Algorithmus läuft extrem langsam. Java Basics - Anfänger-Themen 3
K Erste Schritte Netbeans Programm läuft nicht Java Basics - Anfänger-Themen 23
J Dekrement läuft offenbar falsch Java Basics - Anfänger-Themen 6
A Code läuft nicht, Fehlermeldung Exception in thread "main" java.lang.Error: Unresolved compilation " Java Basics - Anfänger-Themen 11
P Methoden Exception läuft endlos! Java Basics - Anfänger-Themen 7
O Starte Timer, während anderer Timer noch läuft. Ruft dies Schwierigkeiten hervor? Java Basics - Anfänger-Themen 0
D 2d Array läuft nicht rund. Java Basics - Anfänger-Themen 7
F jabva 7.21 läuft nicht auf windows server 2012? Java Basics - Anfänger-Themen 9
T Test läuft schief Java Basics - Anfänger-Themen 3
T SQL Abfrage Läuft nicht Java Basics - Anfänger-Themen 5
C Schleife läuft unendlich Java Basics - Anfänger-Themen 2
H Umgebungsvariable In DOS-Box läuft die fehlerfreie Class-Datei nicht. Java Basics - Anfänger-Themen 5
T OOP Abstrakte Klassen und ihre Kinder: wie läuft das? Java Basics - Anfänger-Themen 3
K Runnable oder Keyadapter läuft falsch Java Basics - Anfänger-Themen 4
N .jar läuft nicht unter Windows 7 Starter Java Basics - Anfänger-Themen 4
S Programm läuft in Eclipse, aber nicht über Konsole Java Basics - Anfänger-Themen 10
A JFrame läuft ewig? Java Basics - Anfänger-Themen 2
S Konsole schließen, nachdem Jar läuft Java Basics - Anfänger-Themen 5
G Events schreiben, solange Programm läuft Java Basics - Anfänger-Themen 6
B Eingabeüberprüfung läuft nicht wie ich das will... Java Basics - Anfänger-Themen 2
K While-Schleife läuft nicht durch Java Basics - Anfänger-Themen 12
F Schleife läuft zu lang Java Basics - Anfänger-Themen 6
P Threads Wann läuft es parallel ab ? Java Basics - Anfänger-Themen 4
M Programm läuft nicht überall Java Basics - Anfänger-Themen 9
O Threads Ein Thread läuft exakt einmal Java Basics - Anfänger-Themen 4
T Programm läuft nicht mehr... Java Basics - Anfänger-Themen 3
F Prüfen ob timer läuft Java Basics - Anfänger-Themen 6
T Erste Schritte Speicher läuft voll, Diashow, Images Java Basics - Anfänger-Themen 7
F sound nur abspielen, wenn er nicht läuft Java Basics - Anfänger-Themen 6
Y Standardprogramm läuft nicht - ppt schreiben Java Basics - Anfänger-Themen 4
D Interpreter-Fehler JavaApplet läuft in der IDE aber nicht im HTML Dokument Java Basics - Anfänger-Themen 9
VfL_Freak Applikation läuft nicht unter Windows7 "platform not supported" Java Basics - Anfänger-Themen 15
A Jlayer: Wie sound stoppen der in einem Thread läuft Java Basics - Anfänger-Themen 7
C Überprüfen, ob Timer läuft Java Basics - Anfänger-Themen 3
P simples Program läuft nicht ;? Java Basics - Anfänger-Themen 9
S jProgressBar läuft nicht! Java Basics - Anfänger-Themen 13
B JavaWebStart - Anwendung läuft nur auf einem Rechner Java Basics - Anfänger-Themen 6
M Audio Stream läuft auf :connection abort: socket write error Java Basics - Anfänger-Themen 2
B Programm läuft mit 100% CPU-Last Java Basics - Anfänger-Themen 6
E Projekt fast fertig, nur es läuft nicht ;) Java Basics - Anfänger-Themen 7
R .jar läuft nicht unter Linux Java Basics - Anfänger-Themen 11
R Jar Datei läuft auf neuem Rechner nicht mehr Java Basics - Anfänger-Themen 15
Z Applet mit Mandelbrot und Juliam. läuft nicht rund Java Basics - Anfänger-Themen 6
P Java Programm läuft nicht auf MAC Java Basics - Anfänger-Themen 7
J Programm läuft in Netbeans, aber nicht in der Konsole Java Basics - Anfänger-Themen 6
L Programm läuft nicht! Warum? Java Basics - Anfänger-Themen 5
G If-Schleife läuft ohne erfüllte Bedingung Java Basics - Anfänger-Themen 13
-horn- Was passiert, wenn Zähler über Integer Max läuft? Java Basics - Anfänger-Themen 9
H Split läuft nicht wie ich will Java Basics - Anfänger-Themen 4
N Brauche dringende Hilfe Java Aplett läuft nicht! Java Basics - Anfänger-Themen 3
G Mittels Runtime prüfen ob ein Programm läuft? Java Basics - Anfänger-Themen 18
A Netbeans unter Windows/Jar läuft nicht auf Mac Java Basics - Anfänger-Themen 7
N FileClassLoader läuft nicht in Tomcat Java Basics - Anfänger-Themen 5
G Was bracuht man, damit Java läuft? Java Basics - Anfänger-Themen 6
G Eine HP mit Java läuft nicht Java Basics - Anfänger-Themen 4
B Programm läuft.aber objektorientiert genug? :( Java Basics - Anfänger-Themen 9
S classe unter windows kompiliert läuft nicht unter linux? Java Basics - Anfänger-Themen 8
G jar läuft nur in eingabeaufforderung Java Basics - Anfänger-Themen 12
P Warum läuft das nicht? Java Basics - Anfänger-Themen 6
L [gelöst] Einfache Aufgabe, läuft aber nicht. Java Basics - Anfänger-Themen 8
S "einfache Klassengeschichten" keine Fehler, läuft Java Basics - Anfänger-Themen 2
G Gauss Applet läuft nicht Java Basics - Anfänger-Themen 9
P kleine db-aufgabe läuft nur suboptimal Java Basics - Anfänger-Themen 8
K eclipse läuft nich Java Basics - Anfänger-Themen 3
M Java läuft nicht Java Basics - Anfänger-Themen 5
I Keine zwei Objekte im Fenster möglich? Was läuft falsch? Java Basics - Anfänger-Themen 5
M Lottoprog. läuft nicht Java Basics - Anfänger-Themen 6
C Applikation läuft nur, wenn sie aus Netbeans gestartet wird Java Basics - Anfänger-Themen 6
C Thread läuft und läuft, trotz interrupt() Java Basics - Anfänger-Themen 9
N läuft der thread eigentlich weiter? Java Basics - Anfänger-Themen 13
M Datenbankabfrage läuft nicht Java Basics - Anfänger-Themen 28
P jbuilder-Programm- Wie läuft es ohne jbuilder. Java Basics - Anfänger-Themen 3
B Choice läuft Amok Java Basics - Anfänger-Themen 10
A For Schleife läuft nicht :( Java Basics - Anfänger-Themen 12
E folgendes kleines Prog läuft net Java Basics - Anfänger-Themen 10

Ähnliche Java Themen

Neue Themen


Oben