2011-11-06 11 views
13

Sto implementando un gioco per 2 giocatori che verrà eseguito in un loop stretto letteralmente centinaia di migliaia di volte, essendo quindi di primaria importanza per le prestazioni.Prestazioni di Java Enums?

mio codice è in realtà qualcosa di simile:

public class Table { 
    private final int WHITE_PLAYER = +1; 
    private final int BLACK_PLAYER = -1; 

    private final int currentPlayer; 
    private final int otherPlayer; 

    ... 
} 

mi chiedevo se avrei avuto alcun calo di prestazioni dovrei scegliere di sostituire

private final int WHITE_PLAYER = +1; 
private final int BLACK_PLAYER = -1; 

ad un enum definito come

public enum Players { 
    WhitePlayer, 
    BlackPlayer 
} 

Ho avuto l'idea che le enumerazioni fossero solo zucchero sintattico rispetto alle costanti intere e che glaze guarda oltre il bytecode generato per un enum di test, così come il codice che lo chiama, sembra indicare che usarli è in effetti lo stesso che effettuare una chiamata di metodo statico ma per qualche infrastruttura enum che viene configurata al primo avvio.

La mia ipotesi è che sia effettivamente lo stesso utilizzare le enumerazioni come costanti statiche corrette o mi manca qualcosa qui?

+0

centinaia di migliaia di volte per quale unità di tempo? –

+1

buona domanda. eseguirò i giochi 24 ore su 24, 7 giorni su 7 (stima), quindi più velocemente finiscono, prima riesco ad analizzare i loro risultati. Imploro le persone a non trasformare questo in una tipica guerra contro il thread di ottimizzazione delle prestazioni .. –

+6

Se pensasse che fosse davvero utile, lo misurerei. –

risposta

20

In un micro-benchmark, sì, controllare l'uguaglianza costante integer sarà più veloce del controllo dell'uguaglianza costante di enum.

Tuttavia, in un'applicazione reale, per non parlare di un gioco, questo sarà totalmente irrilevante. Le cose che accadono nel sottosistema AWT (o in qualsiasi altro toolkit della GUI) rendono minime queste considerazioni sulla micro-prestazione di molti ordini di grandezza.

EDIT

Vorrei esporre un po 'allora.

Un confronto enumerazione così:

aload_0 
getstatic 
if_acmpne 

Un confronto intero per un piccolo intero così:

iload_0 
iconst_1 
if_icmpne 

Ovviamente, il primo è più lavoro rispetto al secondo, anche se la differenza è abbastanza piccolo

eseguire il seguente test case:

class Test { 

    static final int ONE = 1; 
    static final int TWO = 2; 

    enum TestEnum {ONE, TWO} 

    public static void main(String[] args) { 
     testEnum(); 
     testInteger(); 
     time("enum", new Runnable() { 
      public void run() { 
       testEnum(); 

      } 
     }); 
     time("integer", new Runnable() { 
      public void run() { 
       testInteger(); 
      } 
     }); 
    } 

    private static void testEnum() { 
     TestEnum value = TestEnum.ONE; 
     for (int i = 0; i < 1000000000; i++) { 
      if (value == TestEnum.TWO) { 
       System.err.println("impossible"); 
      } 
     } 
    } 

    private static void testInteger() { 
     int value = ONE; 
     for (int i = 0; i < 1000000000; i++) { 
      if (value == TWO) { 
       System.err.println("impossible"); 
      } 
     } 
    } 

    private static void time(String name, Runnable runnable) { 
     long startTime = System.currentTimeMillis(); 
     runnable.run(); 
     System.err.println(name + ": " + (System.currentTimeMillis() - startTime) + " ms"); 
    } 
} 

e vi accorgerete che il confronto enum è più lento che il confronto intero, sulla mia macchina di circa l'1,5%.

Tutto quello che stavo dicendo è che questa differenza non ha importanza in un'applicazione reale ("L'ottimizzazione prematura è la radice di tutto il male"). Mi occupo di problemi prestazionali su base professionale (vedi il mio profilo) e non ho mai visto un punto caldo che possa essere ricondotto a qualcosa di simile.

+2

"Tuttavia, in un'applicazione reale, per non parlare di un gioco, questo sarà del tutto irrilevante: le cose che accadono nel sottosistema AWT (o in qualsiasi altro toolkit GUI) rendono minime queste considerazioni di micro-prestazioni di molti ordini di grandezza." quindi stai assumendo che ci sia davvero una GUI per questo gioco? totalmente falso! –

+1

Perché sarebbe più veloce confrontare un riferimento a 32 bit (uguaglianza identità Enum) con un numero intero a 32 bit? (Ovviamente non si userebbe il metodo '.equals') –

+1

La risposta è errata, a valle. – EJP

8

È necessario disporre di un codice piacevole e leggibile prima che si interessi alle prestazioni. Fino a quando i risultati del profilo (nessuna supposizione!) Dimostrano che le enumerazioni sono il collo di bottiglia, dimenticano le prestazioni e utilizzano tutto ciò che è più facile da capire.

+4

Bello! Non rispondere alla domanda! –

+2

Questo risponde alla tua domanda, semplicemente non capisci o non ti piace la risposta. Bene, questa è la tua scelta. – unbeli

+0

è assolutamente la risposta giusta. Non sarai in grado di distinguere tra l'uso di inte e l'uso di enumerazioni. – MeBigFatGuy

2

JIT sarà ottimizzare un sacco di cose che fanno cose come questa irrilevante dopo che è stato in esecuzione per un po '

per non parlare enumerazioni sono più leggibili e più infallibile si dovrebbe fare un errore nel codice

+0

Ottimizzerà le cose come cosa? – EJP

0

tuo l'ipotesi è corretta Java si assicura che ci sia sempre un'istanza dell'enumerazione in modo che == sia efficiente come confrontare gli interi.

+0

La risposta è errata, a valle. –

+0

@IngoKegel Non corretto in quale particolare esattamente? – EJP

+0

vedi la modifica alla mia risposta –