Ich bin neu in Java und habe letzte Nacht Code ausgeführt, und das hat mich wirklich gestört. Ich habe ein einfaches Programm erstellt, um alle X-Ausgänge in einer for-Schleife anzuzeigen, und ich habe einen massiven Leistungsabfall festgestellt, als ich den Modul als variable % variable
vs variable % 5000
oder so weiter verwendet habe. Kann mir jemand erklären, warum das so ist und was es verursacht? Also kann ich besser sein ...
Hier ist der "effiziente" Code (Entschuldigung, wenn ich ein bisschen falsche Syntax habe, bin ich gerade nicht mit dem Code auf dem Computer)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
Hier ist der "ineffiziente Code"
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
Wohlgemerkt, ich hatte eine Datumsvariable, um die Unterschiede zu messen, und sobald sie lang genug war, dauerte die erste 50 ms, während die andere 12 Sekunden oder so etwas dauerte. Möglicherweise müssen Sie die erhöhen stopNum
oder verringern, progressCheck
wenn Ihr PC effizienter als meiner ist oder was nicht.
Ich habe im Internet nach dieser Frage gesucht, aber ich kann keine Antwort finden. Vielleicht stelle ich sie einfach nicht richtig.
EDIT: Ich hatte nicht erwartet, dass meine Frage so beliebt ist, ich schätze alle Antworten. Ich habe für jede Hälfte der Zeit einen Benchmark durchgeführt, und der ineffiziente Code dauerte erheblich länger, 1/4 Sekunde gegenüber 10 Sekunden Geben oder Nehmen. Zugegeben, sie verwenden println, aber beide machen die gleiche Menge, daher würde ich mir nicht vorstellen, dass dies zu einer starken Verzerrung führen würde, zumal die Diskrepanz wiederholbar ist. Da ich neu in Java bin, werde ich die Stimmen vorerst entscheiden lassen, welche Antwort die beste ist. Ich werde versuchen, bis Mittwoch einen auszuwählen.
EDIT2: Ich werde heute Abend einen weiteren Test durchführen, bei dem anstelle des Moduls nur eine Variable inkrementiert wird. Wenn progressCheck erreicht ist, wird eine durchgeführt und diese Variable für eine dritte Option auf 0 zurückgesetzt.
EDIT3.5:
Ich habe diesen Code verwendet und unten zeige ich meine Ergebnisse. Vielen Dank an ALLE für die wunderbare Hilfe! Ich habe auch versucht, den kurzen Wert des langen mit dem Wert 0 zu vergleichen, sodass alle meine neuen Überprüfungen immer "65536" Mal durchgeführt werden, sodass sie in Wiederholungen gleich sind.
public class Main {
public static void main(String[] args) {
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 65536;
final long finalProgressCheck = 50000;
long date;
// using a fixed value
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if (i % 65536 == 0) {
System.out.println(i);
}
}
long final1 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
//using a variable
for (long i = startNum; i <= stopNum; i++) {
if (i % progressCheck == 0) {
System.out.println(i);
}
}
long final2 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using a final declared variable
for (long i = startNum; i <= stopNum; i++) {
if (i % finalProgressCheck == 0) {
System.out.println(i);
}
}
long final3 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using increments to determine progressCheck
int increment = 0;
for (long i = startNum; i <= stopNum; i++) {
if (increment == 65536) {
System.out.println(i);
increment = 0;
}
increment++;
}
//using a short conversion
long final4 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if ((short)i == 0) {
System.out.println(i);
}
}
long final5 = System.currentTimeMillis() - date;
System.out.println(
"\nfixed = " + final1 + " ms " + "\nvariable = " + final2 + " ms " + "\nfinal variable = " + final3 + " ms " + "\nincrement = " + final4 + " ms" + "\nShort Conversion = " + final5 + " ms");
}
}
Ergebnisse:
- fest = 874 ms (normalerweise um 1000 ms, aber schneller, da es eine Potenz von 2 ist)
- variabel = 8590 ms
- letzte Variable = 1944 ms (war ~ 1000 ms bei Verwendung von 50000)
- Inkrement = 1904 ms
- Kurzumwandlung = 679 ms
Kein Wunder, dass die Short Conversion aufgrund mangelnder Teilung 23% schneller war als der "schnelle" Weg. Das ist interessant zu bemerken. Wenn Sie alle 256 Mal (oder ungefähr dort) etwas zeigen oder vergleichen müssen, können Sie dies tun und verwenden
if ((byte)integer == 0) {'Perform progress check code here'}
EIN ENDGÜLTIGER INTERESSANTER HINWEIS: Die Verwendung des Moduls für die "endgültig deklarierte Variable" mit 65536 (keine hübsche Zahl) war halb so schnell (langsamer) als der feste Wert. Wo vorher war es Benchmarking in der Nähe der gleichen Geschwindigkeit.
final
vor derprogressCheck
Variablen hinzufüge , laufen beide wieder mit der gleichen Geschwindigkeit. Das lässt mich glauben, dass der Compiler oder die JIT es schaffen, die Schleife zu optimieren, wenn sie weiß, dass diesprogressCheck
konstant ist.