Wenn ich in diesem Code ein Objekt in der main
Methode erstelle und diese Objektmethode dann ff.twentyDivCount(i)
aufrufe : (wird in 16010 ms ausgeführt), wird sie viel schneller ausgeführt als mit dieser Anmerkung: twentyDivCount(i)
(wird in 59516 ms ausgeführt). Wenn ich es ausführe, ohne ein Objekt zu erstellen, mache ich die Methode natürlich statisch, damit sie hauptsächlich aufgerufen werden kann.
public class ProblemFive {
// Counts the number of numbers that the entry is evenly divisible by, as max is 20
int twentyDivCount(int a) { // Change to static int.... when using it directly
int count = 0;
for (int i = 1; i<21; i++) {
if (a % i == 0) {
count++;
}
}
return count;
}
public static void main(String[] args) {
long startT = System.currentTimeMillis();;
int start = 500000000;
int result = start;
ProblemFive ff = new ProblemFive();
for (int i = start; i > 0; i--) {
int temp = ff.twentyDivCount(i); // Faster way
// twentyDivCount(i) - slower
if (temp == 20) {
result = i;
System.out.println(result);
}
}
System.out.println(result);
long end = System.currentTimeMillis();;
System.out.println((end - startT) + " ms");
}
}
BEARBEITEN: Bisher scheinen verschiedene Maschinen unterschiedliche Ergebnisse zu liefern, aber bei Verwendung von JRE 1.8. * Scheint das ursprüngliche Ergebnis konsistent reproduziert zu werden.
+PrintCompilation +PrintInlining
gezeigtAntworten:
Mit JRE 1.8.0_45 erhalte ich ähnliche Ergebnisse.
Ermittlung:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
VM-Optionen zeigt, dass beide Methoden kompiliert und eingebunden werdenmain
sehr unterschiedlich, wobei die Instanzmethode aggressiver optimiert wird, insbesondere im Hinblick auf das Abrollen der SchleifeIch habe dann Ihren Test erneut ausgeführt, jedoch mit unterschiedlichen Einstellungen zum Abrollen der Schleife, um den oben genannten Verdacht zu bestätigen. Ich habe Ihren Code ausgeführt mit:
-XX:LoopUnrollLimit=0
und beide Methoden werden langsam ausgeführt (ähnlich der statischen Methode mit den Standardoptionen).-XX:LoopUnrollLimit=100
und beide Methoden laufen schnell (ähnlich der Instanzmethode mit den Standardoptionen).Zusammenfassend scheint es, dass die JIT von Hotspot 1.8.0_45 mit den Standardeinstellungen die Schleife nicht abrollen kann, wenn die Methode statisch ist (obwohl ich nicht sicher bin, warum sie sich so verhält). Andere JVMs können zu anderen Ergebnissen führen.
quelle
Nur eine unbewiesene Vermutung basiert auf der Antwort eines Assylias.
Die JVM verwendet einen Schwellenwert für das Abrollen von Schleifen, der etwa 70 beträgt. Aus irgendeinem Grund ist der statische Aufruf etwas größer und wird nicht abgewickelt.
Ergebnisse aktualisieren
LoopUnrollLimit
in den folgenden 52 sind beide Versionen langsam.Dies ist seltsam, da ich vermute, dass der statische Aufruf in der internen Darstellung nur geringfügig größer ist und das OP einen seltsamen Fall trifft. Aber der Unterschied scheint ungefähr 20 zu sein, was keinen Sinn ergibt.
Für diejenigen, die experimentieren möchten, kann meine Version nützlich sein.
quelle
NON_STATIC
undSTATIC
, aber meine Schlussfolgerung war richtig. Jetzt behoben, danke.Wenn dies im Debug-Modus ausgeführt wird, sind die Zahlen für die Instanz und die statischen Fälle gleich. Dies bedeutet weiter, dass die JIT zögert, den Code im statischen Fall genauso wie im Fall der Instanzmethode zu nativem Code zu kompilieren.
Warum tut es das? Es ist schwer zu sagen; wahrscheinlich würde es das Richtige tun, wenn dies eine größere Anwendung wäre ...
quelle
Ich habe den Test nur leicht angepasst und die folgenden Ergebnisse erhalten:
Ausgabe:
HINWEIS
Während ich sie separat testete, bekam ich ~ 52 Sekunden für dynamisch und ~ 200 Sekunden für statisch.
Dies ist das Programm:
Ich habe auch die Reihenfolge des Tests geändert in:
Und ich habe folgendes:
Wie Sie sehen, hat sich die Geschwindigkeit für Statik drastisch verringert, wenn Dynamik vor Statik aufgerufen wird.
Basierend auf dieser Benchmark:
FAUSTREGEL:
Java: Wann werden statische Methoden verwendet?
quelle
Bitte versuche:
quelle