2013-03-23 23 views
12

Ero curioso di sapere quali fossero le differenze di prestazioni tra la classe Java e il tipo primitivo per il doppio. Così ho creato un piccolo benchmark e ho trovato che il tipo di classe era 3x-7x più lento del tipo primitivo. (3x sulla macchina locale OSX, 7x sulla Ideone)Java Double vs double: tipo classe vs tipo primitivo

Ecco il test:

class Main { 
    public static void main(String args[]) { 
     long bigDTime, littleDTime; 

     { 
      long start = System.nanoTime(); 
      Double d = 0.0; 
      for (Double i = 0.0; i < 1432143.341; i += 0.1) { 
       d += i; 
      } 
      long end = System.nanoTime(); 
      bigDTime = end - start; 
      System.out.println(bigDTime); 
     } 

     { 
      long start = System.nanoTime(); 
      double d = 0.0; 
      for (double i = 0.0; i < 1432143.341; i += 0.1) { 
       d += i; 
      } 
      long end = System.nanoTime(); 
      littleDTime = end - start; 
      System.out.println(littleDTime); 
     } 

     System.out.println("D/d = " + (bigDTime/littleDTime)); 
    } 
} 

http://ideone.com/fDizDu

Allora, perché è il tipo Double in modo molto più lento? Perché è persino implementato per consentire agli operatori matematici?

+1

È lento a causa della necessità di box e unbox. Questo è un comportamento previsto. –

+0

@HovercraftFullOfEels Questo ha senso, ma sembra ancora un sacco di spese generali. –

+1

È un sacco di spese generali. E per questo motivo si dovrebbe evitare l'uso di tipi di wrapper primitivi in ​​codice time-critical. –

risposta

17

Quindi perché il tipo Double è molto più lento?

Poiché il valore è avvolto all'interno di un oggetto che deve allocazione, deallocazione, gestione della memoria più getter e setter

Perché ancora implementata per permettere agli operatori matematici?

Perché autobox ha lo scopo di consentire l'utilizzo di tali wrapper senza preoccuparsi del fatto che non siano semplici valori. Preferiresti non essere in grado di avere un ArrayList<Double>? Le prestazioni sono non sempre necessarie e una goccia di 3x-7x di prestazioni in base alle situazioni può essere accettabile. L'ottimizzazione è un requisito che non è sempre presente.

Questo è vero in ogni situazione, utilizzando un LinkedList agli elementi ad accesso casuale potrebbe essere eccessivo, ma questo non significa che LinkedList non dovrebbe essere implementato a tutti. Ciò non significa nemmeno che l'utilizzo di un elenco collegato per pochi accessi casuali potrebbe interferire così tanto con le prestazioni.

Una nota finale: è necessario lasciare che la VM si scaldi prima di eseguire il benchmark di tali elementi.

3

Double è un double scatolato. Quindi, in generale, il codice compilato deve controllare lo Double per null prima di fare qualcosa con esso. Questo è ovviamente più lento del non fare nulla.

Double (e altre versioni in scatola dei primitivi) è utile perché è un Object. Ciò ti consente di passare a funzioni che richiedono uno Object e di ricollocarlo su Double da un'altra parte. Più utile, consente ai tipi generici di contenerlo: un tipo generico non può contenere double o qualsiasi altra primitiva, ma può contenere un Double.

8

Normalmente non si usa Double, Integer, ecc (Occasionalmente Integer ecc può essere utile per memorizzare un valore 'optional' -. Si potrebbe desiderare di essere null A volte questo è meno probabile con Double perché NaN è disponibile per quelli.)

Il motivo Double esiste come segue. Java ha due tipi principali di valori: oggetti (essenzialmente come i puntatori C/C++ senza l'aritmetica) e valori primitivi (ad esempio double).Classi come ArrayList possono essere definiti per accettare qualsiasi Object, che consente agli utenti di memorizzare String, File o qualsiasi cosa vogliano in uno - ma i valori primitivi come double non sono coperti da tale definizione. Quindi esistono classi come Double per rendere più semplice per classi come ArrayList memorizzare double s, senza richiedere agli autori di ArrayList di creare versioni speciali per tutti i tipi primitivi.