Eine Frage zur Bearbeitungszeit

civben85

Mitglied
Hallo,

ich hätte mal eine Frage zum Ablauf von Methoden und der Bearbeitungszeit:

Wenn ich eine Methode zweimal sehr dicht hintereinander aufrufe, wird dann das Ergebnis kurzzeitig irgendwo zwischengespeichert oder so? Ich habe hier zwei Methoden laufen lassen, einmal speichere ich den Rückgabewert in einer Variable und einmal rufe ich die Methode jeweils wieder neu auf.

Dann habe ich die zwei Sachen laufen lassen(extra übertrieben lang) und habe aber gleich lange Laufzeiten für das Programm bekommen (jeweils +/- 34000 ms).

Also wie gesagt, meine Frage: Werden Methodenergebnisse kurzzeitig zwischengespeichert, so dass erneute Methodenaufrufe einfach auf den Rückgabewert zugreifen können?

Code:
Java:
public static long euler036a() {
		for(int i = 1; i < 1000000; i++) {
			boolean pal = isPalinDecimalism(i);
			if(pal) System.out.println(i + " isPal: " + pal);
		}
		return -1;
	}

public static long euler036b() {
		for(int i = 1; i < 1000000; i++) {
			if(isPalinDecimalism(i)) System.out.println(i + " isPal: " + isPalinDecimalism(i));
		}
		return -1;
	}

in eulerb müsste die Methode isPalinDecimalism ja eigentlich zweimal durchlaufen werden und damit das Programm eine höhere Laufzeit haben, oder habe ich irgendwo einen Denkfehler?

Danke!
 
Ich spekuliere, vielleicht hat die JVM Deinen Code automatisch im Hintergrund optimiert und nach so vielen Schleifenaufrufen selbst gemerkt, daß ein bestimmtes Objekt immer wieder vorkommt, darum heißt ja eine bekannte VM eben Hotspot-VM.

Ab wann bzw. ab wievielen Aufrufen die VM zu optimieren beginnt, oder ob vielleicht schon der Compiler den Code umgestellt hat (Assembler-Analyse des Byte-Code?), kann ich Dir aber nicht beantworten, für Compiler- oder VM-Tuning bin ich kein Experte.
 
in eulerb müsste die Methode isPalinDecimalism ja eigentlich zweimal durchlaufen werden und damit das Programm eine höhere Laufzeit haben, oder habe ich irgendwo einen Denkfehler?
Ja, müsste es. Der mögliche Denkfehler könnte sein, dass
Code:
isPalinDecimalism(i)
für die meisten Zahlen
Code:
false
returnt. In diesem Fall wird diese Methode nämlich auch bei
Code:
euler036b()
nur einmal aufgerufen, weil der if-Block nicht betreten wird.
 
Es gibt eine sehr einfache Erklärung für das ganze.

Nimm zwei Personen. A ist 2,20 m groß. B ein Kind 1,00 m. Der Größenunterschied ist vergleichsweise gewaltig. A/B = 2,2

Jetzt stell Beide auf ein 100 Meter hohes Gebäude und miß die Höhe des Gebäudes und der Person.

A 102,2 m
B 101,0 m

Wenn man nun vergleicht bekommt man ein Verhältnis von A/B = 1,0119. Beide sind demnach fast gleich groß.

Genau das passiert bei deinem Code.

System.out.println ist sehr sehr langsam im Vergleich zu einer einzigen Berechnung von
Code:
isPalinDecimal()
.

Der Faktor der println() langsamer ist würde ich so in die Größenordnung von 100 einordnen.

Bei der Aufgabe geht es ja zudem um das Projekt Euler Aufgabe 36. Eine Kurze Internetrecherche führt zu einer Implementierung in C# die laut angaben, die komplette Aufgabe löst. Also auch die Überprüfung auf "isPalinBinary()" und wie in der Aufgabenstellung die Werte addiert anstatt Sie einzeln auszugeben. Die Rechenzeit für ebenfalls 1 Mio Einträge, beträgt dort nur ca. 120 ms insgesamt.

Dies nur zur Ergänzung von nillehammer
 
Ja das mit der If-Bedingung stimmt, da ist man sowieso selten drin :autsch: ...
Und dass das System.out hier ausbremst kann auch sein.

Aber mir ging es sowieso eher prinzipiell darum wie Java damit umgeht, wenn die gleiche Methode mit den gleichen Parametern öfters hintereinander aufgerufen wird. Also sagen wir wir haben eine Methode (public int takesTime() ), die einen int zurückgibt und sehr lange dauert bsp. 100ms.

Dann wäre die Dauer von
Java:
int x = takesTime();
int y = takesTime();
ja theoretisch ca. 200ms weil takesTime() zweimal durchlaufen wird.

Allerdings wäre
Java:
int x = takesTime();
int y = x;
ja theoretisch dann ca. doppelt so schnell.

Darum ging es mir.

Daher vielen Dank an Meno, das mit der Optimierung der VM ist interessant und gut zu wissen.

Änderung:

Ach und meine Euler36-Methode dauert auch nicht so ewig, ich hab mich nur beim erstellen danach gefragt wie solche Methodenaufrufe gehandhabt werden und dann die Schleife nicht bis 10^6 sondern 10^9 laufen lassen damit man etwaige Unterschiede in der Laufzeit sieht 🙂. thx
 
Zuletzt bearbeitet:
Nur weils dich interessiert:

In Java wird jede Methode IMMER abgearbeitet, weil Seiteneffekte vorkommen können.

In deinem Beispiel kann der Compiler ja nicht wissen, dass der zweite Aufruf von takesTime() das gleiche Ergebnis liefert - vielleicht ist I/O im Spiel?

Wenn schon beim Schreiben des Codes klar ist, dass immer der gleiche Rückgabewert entsteht wird sowas manchmal beim Übersetzen vom Compiler wegoptimiert (das passiert aber nur in ziemlich einfachen Fällen).

Was du meinst geht eher in Richtung "funktionale Programmierung", wo Aufrufe mit den gleichen Parametern IMMER das gleiche Ergebnis liefern usw.
 
Genau.

Natürlich kann man selbst memoisieren, z.B. in einer Map alle bisherigen Ergebnisse speichern, und bei jedem Aufruf prüfen, ob das schon mal abgefragt wurde, so dass man sich die Berechnung eventuell sparen kann.
 

Zurück
Oben