SORU
15 AĞUSTOS 2014, Cuma


Neden &; while (i < n) " {} " daha önemli ölçüde daha yavaş "while ( i < n) {}"

Görünüşe göre benim Windows Fi ile 8 laptop 1.7.0_45 (varsayılan tüm derleyici/VM seçenekleri ayarlayın, aşağıdaki döngü ile İLGİLENİYORUZ

final int n = Integer.MAX_VALUE;
int i = 0;
while (  i < n) {
}

büyüklük ise daha hızlı (vs~5000 ms ms ~10) daha en az 2 sipariş

final int n = Integer.MAX_VALUE;
int i = 0;
while (i   < n) {
}

Başka bir alakasız performans sorunu değerlendirmek için bir döngü yazarken bu sorunu fark ettim. i < n i < n arasındaki fark anlamlı sonucu etkilemek için yeterince büyük.

Eğer koduna bakacak olursak, daha hızlı sürümü döngü cesedini

iinc
iload
ldc
if_icmplt

Ve daha yavaş versiyonu:

iload
iinc
ldc
if_icmplt

i < n, Bu yüzden ilk 1 tarafından yerel değişken i kademeli ve yığın i < n ters sırada bu 2 adım yok iken işlenen üzerine itin. Ama o eski çok daha hızlı olduğunu açıklamak görünmüyor. Herhangi bir geçici kopyasının ikinci durumda yer var mı? Ya da Java (VM uygulama, donanım, vb.) ötesinde bir şey. bu performans farkı için sorumlu olmalıdır?

Okudum başka bir tartışma konusunda i i (tamamen değil ama), ama bulamadınız cevap Java-özel doğrudan ilgili durumda i i dahil değeri karşılaştırma.

CEVAP
15 AĞUSTOS 2014, Cuma


Diğerleri belirttiği gibi, bu test birçok yönden kusurludur.

Bize tam olarak söylemedinnasılbu test yaptın. Ancak, bir "," test (alınmayın) bu gibi: . saf uygulamaya çalıştım

class PrePostIncrement
{
    public static void main(String args[])
    {
        for (int j=0; j<3; j  )
        {
            for (int i=0; i<5; i  )
            {
                long before = System.nanoTime();
                runPreIncrement();
                long after = System.nanoTime();
                System.out.println("pre  : " (after-before)/1e6);
            }
            for (int i=0; i<5; i  )
            {
                long before = System.nanoTime();
                runPostIncrement();
                long after = System.nanoTime();
                System.out.println("post : " (after-before)/1e6);
            }
        }
    }

    private static void runPreIncrement()
    {
        final int n = Integer.MAX_VALUE;
        int i = 0;
        while (  i < n) {}
    }

    private static void runPostIncrement()
    {
        final int n = Integer.MAX_VALUE;
        int i = 0;
        while (i   < n) {}
    }
}

Varsayılan ayarlar ile çalışırken, küçük bir fark var gibi görünüyor. Amagerçekkriter kusur -server bayrağı ile bu çalışma ne zaman belli olur. Benim durumumda sonuçları o zaman boyunca bir şey gibi

...
pre  : 6.96E-4
pre  : 6.96E-4
pre  : 0.001044
pre  : 3.48E-4
pre  : 3.48E-4
post : 1279.734543
post : 1295.989086
post : 1284.654267
post : 1282.349093
post : 1275.204583

Belli ki, artırma öncesi sürüm olmuşturtamamen uzak optimize edilmiş. Nedeni oldukça basit: neden kullanılmaz. Döngü yürütülür olsun ya da olmasın hiç önemli değil, JİT sadece kaldırır.

Bu etkin çözümü bir göz tarafından onaylandıktan: önceden arttırma sürümü bu kod: sonuç

[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} {0x0000000055060500} 'runPreIncrement' '()V' in 'PrePostIncrement'
  #           [sp 0x20]  (sp of caller)
  0x000000000286fd80: sub    $0x18,%rsp
  0x000000000286fd87: mov    %rbp,0x10(%rsp)    ;*synchronization entry
                                                ; - PrePostIncrement::runPreIncrement@-1 (line 28)

  0x000000000286fd8c: add    $0x10,%rsp
  0x000000000286fd90: pop    %rbp
  0x000000000286fd91: test   x,-0x243fd97(%rip)        # 0x0000000000430000
                                                ;   {poll_return}
  0x000000000286fd97: retq   
  0x000000000286fd98: hlt    
  0x000000000286fd99: hlt    
  0x000000000286fd9a: hlt    
  0x000000000286fd9b: hlt    
  0x000000000286fd9c: hlt    
  0x000000000286fd9d: hlt    
  0x000000000286fd9e: hlt    
  0x000000000286fd9f: hlt    

Olayı sürümünü bu kodun:

[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} {0x00000000550605b8} 'runPostIncrement' '()V' in 'PrePostIncrement'
  #           [sp 0x20]  (sp of caller)
  0x000000000286d0c0: sub    $0x18,%rsp
  0x000000000286d0c7: mov    %rbp,0x10(%rsp)    ;*synchronization entry
                                                ; - PrePostIncrement::runPostIncrement@-1 (line 35)

  0x000000000286d0cc: mov    $0x1,%r11d
  0x000000000286d0d2: jmp    0x000000000286d0e3
  0x000000000286d0d4: nopl   0x0(%rax,%rax,1)
  0x000000000286d0dc: data32 data32 xchg %ax,%ax
  0x000000000286d0e0: inc    %r11d              ; OopMap{off=35}
                                                ;*goto
                                                ; - PrePostIncrement::runPostIncrement@11 (line 36)

  0x000000000286d0e3: test   x,-0x243d0e9(%rip)        # 0x0000000000430000
                                                ;*goto
                                                ; - PrePostIncrement::runPostIncrement@11 (line 36)
                                                ;   {poll}
  0x000000000286d0e9: cmp    $0x7fffffff,%r11d
  0x000000000286d0f0: jl     0x000000000286d0e0  ;*if_icmpge
                                                ; - PrePostIncrement::runPostIncrement@8 (line 36)

  0x000000000286d0f2: add    $0x10,%rsp
  0x000000000286d0f6: pop    %rbp
  0x000000000286d0f7: test   x,-0x243d0fd(%rip)        # 0x0000000000430000
                                                ;   {poll_return}
  0x000000000286d0fd: retq   
  0x000000000286d0fe: hlt    
  0x000000000286d0ff: hlt    

Bu görünüşte neden tamamen benim için net değildeğilsonrası arttırma sürümü kaldırın. (Aslında, ben ayrı bir soru olarak soran düşünün). Ama en azından, bu farklılıkları ile görebilirsiniz açıklıyor "büyüklük sırası"...


EDİT: Integer.MAX_VALUE-1 Integer.MAX_VALUE döngü üst sınırı değişiyor olmasıdırher ikisi desürümleri uzak optimize edilmiş ve "zaman. sıfır gerektirir Bir şekilde bu sınırı hala mecliste 0x7fffffff olarak görüntülenir) optimizasyonu engeller. Muhtemelen, bu karşılaştırma ile ilgili bir şey bir eşlenmiş (yanmış!) cmp talimat, ama onun ötesinde derin bir sebep veremem. Bu JİT gizemli yollarla çalışır...

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Metheud

    Metheud

    9 EYLÜL 2006
  • The Weavers of Eternity Paracord Tutorials

    The Weavers

    1 Ocak 2014
  • TouchePro

    TouchePro

    27 EYLÜL 2007