2009-03-01 28 views
6

Sto provando a fare un benchmarking di JVM in esecuzione su varie piattaforme hardware e OS. Ho creato un algoritmo per esercitare le parti della JVM a cui sono interessato e ho intenzione di eseguire questo algoritmo molte volte per trovare una media decente.Eager java class loading

Quando eseguo il punto di riferimento, trovo che la prima corsa è significativamente più lungo di esecuzioni successive:

132ms 
86ms 
77ms 
89ms 
72ms 

Il mio sospetto è che le classi vengono caricate pigramente, mettere una grande testa alla prima esecuzione. Anche se questa è davvero una caratteristica che presumo sia unica per ogni JVM, non è quella a cui sono interessato a questo punto.

Esiste un'opzione di riga di comando standard o una proprietà per caricare le classi in modo avido? o qualcuno ha altre teorie?

risposta

5

La cosa più semplice da fare è ignorare la prima corsa. (Se questa è una cosa valida da fare) Nota: se si esegue lo stesso codice 10.000 volte, si compila ulteriormente il codice e si ottengono risultati migliori, quindi è possibile ignorare i primi risultati 10K per alcuni micro-benchmark.

Alcune JVM supportano il carico impaziente, ma non credo che la JVM di Sun funzioni.

+0

Non riesco a farlo compilare ulteriormente il codice. per favore approfondisci su questo, e perché solo dopo 10000 volte eseguire, si possono ottenere i risultati appropriati per micro-benchmarking (media) –

+0

La "soglia del compilatore" predefinita è 10000. si veda '-XX: CompileThreshold = 10000' Questo può significare che il codice non è completamente ottimizzato finché non viene eseguito 10.000 e potresti voler ignorare queste esecuzioni per ottenere i risultati migliori. In ogni caso suggerisco di eseguire il test per almeno 2-10 secondi. –

+0

in questo caso se do -XX: CompileThreshold = 10, allora siamo bravi a testarlo per un ciclo di 10000 (sì, so che verrà eseguito solo per alcuni millisecondi) –

2

Utilizzare java -XX:+TraceClassLoading per tracciare il caricamento delle classi.

Utilizzare java -XX:+PrintCompilation per tracciare quando i metodi sono JIT.

0

Non esiste un'opzione di riga di comando standard, poiché non fa parte delle specifiche JVM. Il caricamento della classe Lazy è (esplicitamente consentito come) parte delle specifiche JVM. Sarebbe possibile utilizzare Class.forName() prima dell'esecuzione per caricare le classi che conosci, ma non è automaticamente transitiva.

La compilazione di HotSpot eseguirà anche le prime esecuzioni: un metodo viene interpretato alcune volte prima di essere compilato e il processo di compilazione richiede un po 'di tempo.

4

Regola n. 1 per il benchmarking Java: le prime 15.000 volte (o così) le esecuzioni di un metodo non sono interessanti.

Questo thread contiene qualche consiglio solido: How do I write a correct micro-benchmark in Java?

+0

In altre parole: Java è veloce se si ignora quando è lento :-) – marcus

4

Se si vuole forzare le classi da caricare fare qualcosa di simile:

public class Main 
{ 
    static 
    { 
     loadClasses(); 
    } 

    public static void main(final String[] argv) 
    { 
     // whatever 
    } 

    private static void loadClasses() 
    { 
     final String[] classesToLoad; 

     // even better, read them from a file and pass the filename to this method 
     classesToLoad = new String[] 
     { 
      "foo.bar.X", 
      "foo.bar.Y", 
     } 

     for(final String className : classesToLoad) 
     { 
      try 
      { 
       // load the class 
       Class.forName(className); 
      } 
      catch(final ClassNotFoundException ex) 
      { 
       // do something that makes sense here 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 
+0

se si vuole caricare le classi, come e quando la classe Main carica, può importare, qual è la necessità di Class.forName –

+0

@Naroji importare è una cosa del compilatore, non fa nulla in fase di esecuzione. – TofuBeer

+0

Convalidare prego ... la classe può essere caricata nell'area metodo jvm da ClassLoader, Class.forName o nuovo Operator, DI, Factory (internamente utilizzano solo classLoader) ... nuovo, DI, Factory crea anche oggetto –

1

Una volta che avete le classi caricate, per evitare l'esecuzione l'interprete utilizzare -Xcomp (su implementazioni Sun) per eseguire solo il codice compilato. Può essere molto lento eseguire le normali applicazioni in questo modo, poiché tutto il codice deve essere compilato piuttosto che solo alcuni pezzi.