Java simpler Benchmark mit unerklärlichen Abweichungen

ApfelHans

Cadet 4th Year
Registriert
Juni 2013
Beiträge
65
Hallo,

bei diesem Benchmark, der die Zeit von 100.000.000 Aufrufen einer abstrakten Methode in Millisekunden angibt, bekomme ich unter Win 8.1 und Java 7 Update 60 bekomme ich zu 70% eie Zeit von 0 ms, 22% 16 ms, 3% 15 ms. Auf alten Apple Systemen und bis Win XP bekam ich immer nur eine Zeit geliefert. Bei Win XP gab es auch eine Aufteilung von 70% auf 32 ms und 30% 16 ms.
Mit dem Benchmark soll gezeigt werden, wie sich versch. Java Versionen auf verschiedener Hardware mit unterschiedlichen OS verhält.
Kann sich jemand erklären wie die Aufteilung zu stande kommt?

public abstract class Benchmark {

public abstract void benchmark();

long repeat ( int count )
{
long start = System.currentTimeMillis();
for( int i=0; i<count; i++)
{
benchmark();
} //for
return (System.currentTimeMillis() - start);
} //repeat
} //class Benchmark

public class MethodBenchmark extends Benchmark {

public void benchmark()
{

} //benchmark

public static void main( String[] args )
{
int count = 1000000000;
long time;

System.out.println( time = new MethodBenchmark().repeat( count ) );

} //main
} //class MethodBenchmark
 
Zuletzt bearbeitet: (Code hinzugefügt)
Es kann sein, dass eine compiler-optimierung stattgefunden hat, d.h. der Aufruf wurde wegoptimiert, da er nichts "sinnvolles" für das Programm erledigt. Dies würde auf jedenfall die Sache mit den 0ms erklären.
Die anderen Zeiten könnten dispatcher Zeiten etc. sein. (sehr waage ...)
 
System.currentTimeMillis() tickt nicht in 1 ms Schritten. Wirst du auch sehen, wenn du dir in einer Schleife mal nur die Zeit ausgeben lässt.

Zusätzlich kommt noch der interne Code Optimierer zum Tragen, der häufig benutzten Code in Maschinencode umwandelt. Wenn mir die genaue Bezeichnung einfällt, poste ich nochmal einen Link.

EDIT: Bitte sehr (JIT) http://de.wikipedia.org/wiki/Just-in-time-Kompilierung
 
Zuletzt bearbeitet:
Das Compileroptimierung ist einleuchtend. Das es nicht immer 1 ms Schritte sind ist mir gar nicht aufgefallen, aber es bleibt ja trotzdem konstant.
 
Ich weiß gerade nicht mehr wie die optimierung heißt, nur die Methode wird wegoptimiert, da sie leer ist. Versuch mal darin irgendeinen Unsinn zu betreiben: (ich weiß das verfäscht die Zeit...)

Code:
static int i = 0;
...
benchmark() {
i++;
}
 
Naja, die Methode benchmark hast du überschrieben und die macht nicht wirklich was. Da optimiert der JIT-Compiler ein wenig und ruft die Schleife erst gar nicht auf.
Es gibt vermutlich verschiedene Werte, weil der Aufruf von "System.currentTimeMillis()" eine native Methode ist, d. h. das Betriebssystem aufgerufen wird und somit Java auf das Ergebnis wartet.

Teste mal das Ganze ohne diese Schleife. Vermutlich bekommst du das gleiche Ergebnis.
 
@SaxnPaule:
JIT ist was gänzlich anderes als häufig verwendeten Code in Maschinencode zu übersetzen. JIT übersetzt eher Code in Echtzeit wenn Bedarf ist -> anders als bei C++ wo der gesamte Code kompiliert werden muss, jedoch zur Ausführungszeit vollständig übersetzt vorliegt.
 
Richtig. Und Bedarf ist da, wenn gleicher Code mehrfach ausgeführt wird. Schreib eine Methode und führe diese 10x hintereinander in einer Schleife aus. Nach dem dritten Durchlauf wird sich die Zeit nicht mehr verkürzen, da der JIT seinen Job getan hat. Kann auch 4 oder 5 Durchläufe dauern.
 
Wenn du 0ms bekommst, kann es auch sein, dass das Programm zu kurz ist, um eine Messung im ms-Bereich machen zu können. Hast du mal System.nanoTime() verwendet?

Den Unterschied findest du u.a. hier: http://stackoverflow.com/questions/351565/system-currenttimemillis-vs-system-nanotime

Ansonsten kann ich mich meinen Vorrednern anschließen. Die Schleife wird vermutlich wegoptimiert, da sie ja im Endeffekt nichts macht.
 
Zurück
Oben