Neden 64 int daha uzun yavaştır?
Windows 8.1 64 Yüzey Pro 2 tablet Java 7 update 45 x 64 (32 bit Java yüklü) ile koşuyorum.
Aşağıdaki kod ben bu tür bir uzun ve bir int i zaman 109ms olduğunda 1688ms alır. Neden 64 bit JVM ile 64 bitlik bir platformda int büyüklük daha uzun (64 bit türü) bir sipariş daha yavaştır?
Sadece benim teorim CPU 32 bit birden 64 bit bir tamsayı eklemek için daha uzun sürer, ama bu pek mümkün görünmüyor. Haswell ripple-carry toplayıcı kullanmıyor sanırım.
Eclipse Kepler bu koÅŸuyorum SR-1, btw.
public class Main {
private static long i = Integer.MAX_VALUE;
public static void main(String[] args) {
System.out.println("Starting the loop");
long startTime = System.currentTimeMillis();
while(!decrementAndCheck()){
}
long endTime = System.currentTimeMillis();
System.out.println("Finished the loop in " (endTime - startTime) "ms");
}
private static boolean decrementAndCheck() {
return --i < 0;
}
}
Burada eşdeğer C kodu (aşağıda), aynı sistem VS 2013 tarafından derlenmiş. sonuçlar Düzenle:uzun: 72265ms int: 74656msBu sonuçlar debug 32 bit modu.
64 bit sürüm:uzun: 875msuzun uzun: 906ms int: 1047ms
Bu gözlemledim sonucu CPU sınırlamaları yerine JVM optimizasyon tuhaflık olduğunu göstermektedir.
#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "limits.h"
long long i = INT_MAX;
using namespace std;
boolean decrementAndCheck() {
return --i < 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Starting the loop" << endl;
unsigned long startTime = GetTickCount64();
while (!decrementAndCheck()){
}
unsigned long endTime = GetTickCount64();
cout << "Finished the loop in " << (endTime - startTime) << "ms" << endl;
}
Bunun tekrar Java 8 RTM çalıştı, önemli bir değişiklik. Edit:
CEVAP
Benim JVM long
s kullandığınızda iç döngü için oldukça basit bu şey yapıyor
0x00007fdd859dbb80: test êx,0x5f7847a(%rip) /* fun JVM hack */
0x00007fdd859dbb86: dec %r11 /* i-- */
0x00007fdd859dbb89: mov %r11,0x258(%r10) /* store i to memory */
0x00007fdd859dbb90: test %r11,%r11 /* unnecessary test */
0x00007fdd859dbb93: jge 0x00007fdd859dbb80 /* go back to the loop top */
int
s kullandığınızda, zor Hileleri,; ilk anladığımı iddia etmiyorum ama içe kıvrık bir döngü Kur gibi görünen bazı screwiness var:
0x00007f3dc290b5a1: mov %r11d,%r9d
0x00007f3dc290b5a4: dec %r9d
0x00007f3dc290b5a7: mov %r9d,0x258(%r10)
0x00007f3dc290b5ae: test %r9d,%r9d
0x00007f3dc290b5b1: jl 0x00007f3dc290b662
0x00007f3dc290b5b7: add $0xfffffffffffffffe,%r11d
0x00007f3dc290b5bb: mov %r9d,ìx
0x00007f3dc290b5be: dec ìx
0x00007f3dc290b5c0: mov ìx,0x258(%r10)
0x00007f3dc290b5c7: cmp %r11d,ìx
0x00007f3dc290b5ca: jle 0x00007f3dc290b5d1
0x00007f3dc290b5cc: mov ìx,%r9d
0x00007f3dc290b5cf: jmp 0x00007f3dc290b5bb
0x00007f3dc290b5d1: and $0xfffffffffffffffe,%r9d
0x00007f3dc290b5d5: mov %r9d,%r8d
0x00007f3dc290b5d8: neg %r8d
0x00007f3dc290b5db: sar $0x1f,%r8d
0x00007f3dc290b5df: shr $0x1f,%r8d
0x00007f3dc290b5e3: sub %r9d,%r8d
0x00007f3dc290b5e6: sar %r8d
0x00007f3dc290b5e9: neg %r8d
0x00007f3dc290b5ec: and $0xfffffffffffffffe,%r8d
0x00007f3dc290b5f0: shl %r8d
0x00007f3dc290b5f3: mov %r8d,%r11d
0x00007f3dc290b5f6: neg %r11d
0x00007f3dc290b5f9: sar $0x1f,%r11d
0x00007f3dc290b5fd: shr $0x1e,%r11d
0x00007f3dc290b601: sub %r8d,%r11d
0x00007f3dc290b604: sar $0x2,%r11d
0x00007f3dc290b608: neg %r11d
0x00007f3dc290b60b: and $0xfffffffffffffffe,%r11d
0x00007f3dc290b60f: shl $0x2,%r11d
0x00007f3dc290b613: mov %r11d,%r9d
0x00007f3dc290b616: neg %r9d
0x00007f3dc290b619: sar $0x1f,%r9d
0x00007f3dc290b61d: shr $0x1d,%r9d
0x00007f3dc290b621: sub %r11d,%r9d
0x00007f3dc290b624: sar $0x3,%r9d
0x00007f3dc290b628: neg %r9d
0x00007f3dc290b62b: and $0xfffffffffffffffe,%r9d
0x00007f3dc290b62f: shl $0x3,%r9d
0x00007f3dc290b633: mov ìx,%r11d
0x00007f3dc290b636: sub %r9d,%r11d
0x00007f3dc290b639: cmp %r11d,ìx
0x00007f3dc290b63c: jle 0x00007f3dc290b64f
0x00007f3dc290b63e: xchg %ax,%ax /* OK, fine; I know what a nop looks like */
içe kıvrık döngü kendini sonra:
0x00007f3dc290b640: add $0xfffffffffffffff0,ìx
0x00007f3dc290b643: mov ìx,0x258(%r10)
0x00007f3dc290b64a: cmp %r11d,ìx
0x00007f3dc290b64d: jg 0x00007f3dc290b640
içe kıvrık döngü, kendisi bir sınav ve düz bir döngü için enkaz daha sonra kod:
0x00007f3dc290b64f: cmp $0xffffffffffffffff,ìx
0x00007f3dc290b652: jle 0x00007f3dc290b662
0x00007f3dc290b654: dec ìx
0x00007f3dc290b656: mov ìx,0x258(%r10)
0x00007f3dc290b65d: cmp $0xffffffffffffffff,ìx
0x00007f3dc290b660: jg 0x00007f3dc290b654
Bu JÄ°T int
döngü 16 kez içe kıvrık çünkü 16 kat daha hızlı bir şekilde değer vermez sürüyor, ama long
döngü göz önüne sermek değildi yani.
Bütünlüğü için, burada kodu denedim:
public class foo136 {
private static int i = Integer.MAX_VALUE;
public static void main(String[] args) {
System.out.println("Starting the loop");
for (int foo = 0; foo < 100; foo )
doit();
}
static void doit() {
i = Integer.MAX_VALUE;
long startTime = System.currentTimeMillis();
while(!decrementAndCheck()){
}
long endTime = System.currentTimeMillis();
System.out.println("Finished the loop in " (endTime - startTime) "ms");
}
private static boolean decrementAndCheck() {
return --i < 0;
}
}
Montaj döker seçenekleri -XX: UnlockDiagnosticVMOptions -XX: PrintAssembly
kullanılarak üretildi. Etrafında senin için bu iş de JVM yükleme ile uğraşmak gerekir; tam olarak doğru yerde rastgele bir paylaşımlı kütüphane koymak gerekir ya da başarısız olur unutmayın.
Neden baskı "B" baskı " ...
Neden Standart girdiden okuma satır Py...
Neden malloc calloc memset daha yavaÅŸt...
Neden uzun bir dize küçük dizeleri çok...
Neden Azure Dağıtım Windows üzerinde d...