2012-09-01 17 views
8

Sono in procinto di eseguire il porting su un determinato algoritmo di elaborazione dati da Java a C++. La ragione per riscrivere il codice è la portabilità, deve essere eseguita in ambienti in cui Java non è disponibile. Tuttavia, come beneficio a parte, era previsto un miglioramento delle prestazioni.Quanto costa caro .getClass() in Java?

In sostanza, l'algoritmo legge i dati da un grafico costituito da oggetti con puntatori e calcola un risultato. Durante il calcolo vengono effettuate numerose assegnazioni di oggetti, quindi forse questo è responsabile del rallentamento. Il fatto è che il codice C++ attualmente funziona circa 10 volte più velocemente del vecchio codice Java. Questo è stato davvero inaspettato. Ho solo pensato di vedere un miglioramento di circa il 50-60%.

Purtroppo, non sono libero di inserire qui il codice per l'analisi. Sono diverse migliaia di righe, quindi non sono sicuro di quanto sarebbe comodo comunque.

Il fatto è che l'algoritmo è quasi esattamente lo stesso. L'unica grande differenza che posso pensare è in Java ci sono molte classi figlie di una singola super classe e se (object.getClass() == daughterx.class) viene chiamata più volte durante il calcolo mentre nel codice C++ solo una generale la classe è usata (poiché ci sono poche differenze di codice tra le classi figlie) e viene usato un semplice confronto di interi, ad es. if (oggetto-> tipo == 15)

Quanto è costoso il metodo Object.getClass() in Java? Cosa sta succedendo esattamente al livello basso quando viene invocato questo metodo?

+5

@ xlc0212 Né sono una qualsiasi delle altre persone che non capiscono Java ! ;) – cheeken

+0

@cheeken dipende dalla JVM, senza JIT, ricordo di aver letto da qualche parte che Java è anche più lento di python –

+3

Onestamente questo suona come un non-problema. Vale la pena dedicare tempo al benchmark e al profilo del codice deprecato? A meno che tu non lo abbia fatto, non c'è modo di sapere che '.getClass()' è il collo di bottiglia. Indovinare non è un modo utile per eseguire il debug dei problemi di prestazioni, a meno che non sia possibile ridurre in modo significativo la complessità complessiva di un algoritmo (passando da un'operazione N al quadrato a un'operazione di log-N) e il set di dati è molto grande. –

risposta

7

Il caso più probabile per una differenza di 10 volte è che la JVM non è stata completamente scaldata. Se non lo fai puoi vedere più di 10 volte la differenza di prestazioni anche in Java. Vorrei provare a eseguire in batch di 10.000 e ignorare le prime esecuzioni.

public static void main(String... args) throws IOException { 
    timeObjectGraph("First run", 1); 
    timeObjectGraph("Second run", 2); 
    timeObjectGraph("Next thousand", 1000); 
    for (int i = 0; i < 5; i++) 
     timeObjectGraph("Next ten thousand", 10000); 
} 

static int dontOptimiseAway = 0; 

public static void timeObjectGraph(String desc, int runs) throws IOException { 
    long start = System.nanoTime(); 
    for (int i = 0; i < runs; i++) { 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(out); 
     oos.writeObject(Calendar.getInstance()); 
     oos.close(); 
     dontOptimiseAway = out.toByteArray().length; 
    } 
    long time = System.nanoTime() - start; 
    System.out.printf("%s took an avg time of %,d ns%n", desc, time/runs); 
} 

stampe

First run took an avg time of 37,509,488 ns 
Second run took an avg time of 439,054 ns 
Next thousand took an avg time of 185,242 ns 
Next ten thousand took an avg time of 41,698 ns 
Next ten thousand took an avg time of 19,981 ns 
Next ten thousand took an avg time of 11,541 ns 
Next ten thousand took an avg time of 13,451 ns 
Next ten thousand took an avg time of 11,289 ns 

Dalla prima all'ultima corsa, la prestazione è migliorata di un fattore di 3000x

+0

Perché usi Calendar.getInstance()? Innanzitutto la domanda riguarda il metodo getClass. Secondo Calendar è ** pesante ** la classe da creare, quindi Calendar.getInstance() ** è costoso da solo **, non perché getClass viene chiamato all'interno. Penso che questo esempio non sia corretto o dovresti fornire un commento più chiaro. – Cherry

+2

@Cherry Ho usato Calendar e ObjectOutputStream perché sono costosi per un breve pezzo di codice, questo fornisce un esempio realistico di quanto riscaldamento possa fare la differenza per una quantità significativa di codice. –

5

Non è probabile che sia l'unico fattore nella differenza di prestazioni. Sfortunatamente, senza un'immagine molto più completa di ciò che sta facendo il tuo codice, sarà davvero difficile dirti cosa sta succedendo.

Nella mia esperienza non c'è motivo per cui Java dovrebbe essere 10 volte più lento del C++. Probabilmente inizierei con un profiler e vedrei dove punta a capire il problema, piuttosto che a indovinare.

11

Quanto è costoso il metodo Object.getClass() in Java?

Sulla base della mia conoscenza di come viene implementato in JVM non-mainstream, è a buon mercato

Che cosa esattamente sta accadendo a basso livello quando questo metodo viene richiamato?

genere ...

  1. Estrarre l'indice di classe dalla intestazione dell'oggetto (2 o 3) istruzioni
  2. Lookup il descrittore di classe dall'indice di classe (2 o 3) istruzioni
  3. Recupera e restituisci il riferimento dell'oggetto Class dal descrittore di classe (2 o 3 istruzioni)

Il fatto è che il codice C++ è attualmente eseguito circa 10 volte più velocemente del vecchio codice Java.

Mi aspetto che il collo di bottiglia delle prestazioni sia da un'altra parte. Dovresti provare a profilare il codice Java prima di saltare a conclusioni sul motivo per cui è stato più lento.

+6

+1 Anche se la ricerca stessa è economica, implica un significativo problema di progettazione e prestazioni se si dispone di sequenze di 'if (getClass() == SomeClass.class)' Suggerisce di aver bisogno di più OO Design o come l'OP, combinare queste classi in modo che possa utilizzare un interruttore o simili per la funzionalità. –

Problemi correlati