2011-11-18 8 views
8

Per curiosità, ho misurato le prestazioni tra il blocco statico e l'inizializzatore del metodo statico. Innanzitutto, ho implementato i metodi sopra menzionati in due classi Java separati, in questo modo:Blocco statico rispetto al metodo statico - inizializzazione dei campi statici

primo:

class Dummy { 
    static java.util.List<Integer> lista = new java.util.ArrayList<Integer>(); 
    static { 
     for(int i=0; i < 1000000; ++i) { 
      lista.add(new Integer(i)); 
     } 
    } 
} 

public class First { 
    public static void main(String[] args) { 
     long st = System.currentTimeMillis(); 
      Dummy d = new Dummy(); 
     long end = System.currentTimeMillis() - st; 
     System.out.println(end);  
    } 
} 

Secondo:

class Muddy { 
    static java.util.List<Integer> lista = new java.util.ArrayList<Integer>(); 
    public static void initList() { 
     for(int i=0; i < 1000000; ++i) { 
      lista.add(new Integer(i)); 
     } 
    } 
} 

public class Second { 
    public static void main(String[] args) { 
     long st = System.currentTimeMillis(); 
      Muddy.initList(); 
      Muddy m = new Muddy(); 
     long end = System.currentTimeMillis() - st; 
     System.out.println(end);  
    } 
} 

Poi eseguito this piccolo script batch per misurare 100 volte e inserire i valori in un file. batchFile.bat First Second dum.res.txt

Successivamente, ho scritto this parte di codice per calcolare il valore medio e la deviazione standard dei valori misurati di Dummy e di Muddy.

questo è il risultato che ho:

First size: 100 Second size: 100 
First  Sum: 132 Std. deviation: 13 
Second  Sum: 112 Std. deviation: 9 

ed è simile alle mie altre macchine ... ogni volta che provarlo.

Ora mi chiedo, perché è così? Ho controllato il bytecode e Second.class ha un'altra istruzione (chiamata a initList() statico) tra le chiamate a System.currentTimeMillis(). Entrambi fanno la stessa cosa, ma perché il primo è più lento? Non riesco a capirlo davvero solo guardando il bytecode, poiché questa era la prima volta che toccavo javap; Non ho ancora capito il codice byte.

+0

Prova a invertire prima e secondo nella tua chiamata allo script batch e vedere quali sono i risultati :) – antlersoft

+0

Il numero di istruzioni non ha nulla a che fare con quanto tempo impiegano queste istruzioni (che ti dice di attraversare la città piuttosto che attraversare il paese - bene, a meno che non vivi a Lichenstein o qualcosa del genere). Sono esattamente le stesse istruzioni? Ne dubito piuttosto. In una nota a margine, sarei riluttante a usare la tua seconda versione, anche se è più veloce - si basa sul fare quella chiamata 'initList()', qualcosa su cui non avrei mai fatto affidamento. –

+0

@antlersoft Restituisce gli stessi risultati. Già testato. – Mechkov

risposta

2

Penso che la ragione per cui la versione blocco statico è più lento rispetto alla versione metodo statico potrebbe essere dovuto al diverso ottimizzazione JIT che ottengono ...

Vedere questo articolo interessante per informazioni più interessanti: Java Secret: Are static blocks interpreted?

2

Ecco la mia ipotesi per quanto riguarda il motivo per questo:

l'inizializzazione si sta facendo è la creazione di sufficienti oggetti che sta causando uno o più garbage collection.

Quando l'inizializzazione viene richiamata dal blocco statico, viene eseguita durante l'inizializzazione della classe anziché durante l'esecuzione semplice del metodo. Durante l'inizializzazione della classe, il rilevatore di dati inutili potrebbe avere un po 'più di lavoro da fare (perché lo stack di esecuzione è più lungo, ad esempio) che durante l'esecuzione semplice del metodo, anche se il contenuto dell'heap è quasi lo stesso.

Per verificarlo, è possibile provare ad aggiungere -Xms200m o qualcosa ai propri comandi java; questo dovrebbe eliminare la necessità di raccogliere i rifiuti durante l'inizializzazione che stai facendo.