L = 1 long s1 = 0;
for (int i=0; i < L; i++) {
for (int j = 0; j < L; j++) {
s1 += 1;
dış döngü varsayalım : 0 iç döngü: 0 İç döngü: 1 dış döngü: toplam
int i = 0;
long s2 = 0;
do {
i++;
int j = 0;
do {
s2 += 1;
j++;
} while (j < L);
} while (i < L);
iç döngüde 1
4 karşılaştırma: 1 dış döngü: 1
2 karşılaştırmaların toplamı:
- Farklı oluşturulan baytkodlarına
fazla araştırma amacıyla bunu çalışma şeklini etkileyen değil, hafifçe sınıf değişti.
public class Loops {
final static int L = 100000; // number of iterations per loop
public static void main(String[] args) {
int round = 10;
while (round-- > 0) {
forLoop();
doWhileLoop();
whileLoop();
}
}
private static long whileLoop() {
int i = 0;
long s3 = 0;
while (i++ < L) {
int j = 0;
while (j++ < L) {
s3 += 1;
}
}
return s3;
}
private static long doWhileLoop() {
int i = 0;
long s2 = 0;
do {
int j = 0;
do {
s2 += 1;
} while (++j < L);
} while (++i < L);
return s2;
}
private static long forLoop() {
long s1 = 0;
for (int i = 0; i < L; i++) {
for (int j = 0; j < L; j++) {
s1 += 1;
}
}
return s1;
}
}
Sonra derlenmiş ve bayt kodu almak için javap -c -s -private -l Loop
çağrılan.
İlk olarak doWhileLoop'un bayt kodu. Şimdi
0: iconst_0 // push the int value 0 onto the stack
1: istore_1 // store int value into variable 1 (i)
2: lconst_0 // push the long 0 onto the stack
3: lstore_2 // store a long value in a local variable 2 (s2)
4: iconst_0 // push the int value 0 onto the stack
5: istore 4 // store int value into variable 4 (j)
7: lload_2 // load a long value from a local variable 2 (i)
8: lconst_1 // push the long 1 onto the stack
9: ladd // add two longs
10: lstore_2 // store a long value in a local variable 2 (i)
11: iinc 4, 1 // increment local variable 4 (j) by signed byte 1
14: iload 4 // load an int value from a local variable 4 (j)
16: iload_0 // load an int value from a local variable 0 (L)
17: if_icmplt 7 // if value1 is less than value2, branch to instruction at 7
20: iinc 1, 1 // increment local variable 1 (i) by signed byte 1
23: iload_1 // load an int value from a local variable 1 (i)
24: iload_0 // load an int value from a local variable 0 (L)
25: if_icmplt 4 // if value1 is less than value2, branch to instruction at 4
28: lload_2 // load a long value from a local variable 2 (s2)
29: lreturn // return a long value
while döngüsü içinde baytkodu:
0: iconst_0 // push int value 0 onto the stack
1: istore_1 // store int value into variable 1 (i)
2: lconst_0 // push the long 0 onto the stack
3: lstore_2 // store a long value in a local variable 2 (s3)
4: goto 26
7: iconst_0 // push the int value 0 onto the stack
8: istore 4 // store int value into variable 4 (j)
10: goto 17
13: lload_2 // load a long value from a local variable 2 (s3)
14: lconst_1 // push the long 1 onto the stack
15: ladd // add two longs
16: lstore_2 // store a long value in a local variable 2 (s3)
17: iload 4 // load an int value from a local variable 4 (j)
19: iinc 4, 1 // increment local variable 4 (j) by signed byte 1
22: iload_0 // load an int value from a local variable 0 (L)
23: if_icmplt 13 // if value1 is less than value2, branch to instruction at 13
26: iload_1 // load an int value from a local variable 1 (i)
27: iinc 1, 1 // increment local variable 1 by signed byte 1
30: iload_0 // load an int value from a local variable 0 (L)
31: if_icmplt 7 // if value1 is less than value2, branch to instruction at 7
34: lload_2 // load a long value from a local variable 2 (s3)
35: lreturn // return a long value
Her talimat Java bytecode instruction listings dayalı gelmez anlatan yorumlarınızı ekleyebilirsiniz gelmiş çıkış daha okunabilir hale getirmek için.
Daha yakından incelerseniz, bu iki bayt kodu arasında önemli bir fark olduğunu göreceksiniz. while döngüsü (aynı for döngü için de geçerlidir) bayt kodu sonunda tanımlanmış if ifadeleri (if_icmplt
talimatı) içerir. Bunun anlamı, birinci ilmiğin çıkış koşulunu kontrol etmek için bir satırın (26) satırın (26) çağrılması ve benzer şekilde ikinci döngü için bir satırın (17) olmasıdır.
yukarıdaki baytkodu Mac OS X'te Javac 1.6.0_45 kullanılarak oluşturulmuştur
Özeti bence
karşılaştırmalar farklı miktarda artı süre ve döngü bayt için git talimatlarının varlığı Bu döngüler arasındaki performans farkından sorumludur.
Numaralarınızı çoğalamıyorum. Her ikisi de döngüler için biraz daha yavaş döngü için benimle aynı hızı çalıştırın. – Mysticial
Her durumda, derleyici veya JIT iç döngüyü tamamen kaldırabileceğinden, bu özellikle büyük bir kıyaslama değildir. – Mysticial
Durum böyle olmalı - sadece do-while döngüsü için çalıştırılan bir çeşit optimizasyon. Yine de, bu mekanizma hakkında daha çok şey öğrenmek isterim. – JohnF