2013-09-16 14 views
6

Oggi ho eseguito un semplice test per confrontare la velocità tra java e c - un semplice ciclo che fa incrementare un intero "i" da 0 a 2 miliardi.Java più veloce di C

Mi aspettavo davvero che il linguaggio c fosse più veloce di java. Sono rimasto sorpreso dal risultato:

il tempo impiegato in secondi per Java: circa. 1,8 secondi

il tempo impiegato in secondi per c: circa. 3.6 secondi.

NON penso che java sia un linguaggio più veloce, ma NON capisco neanche perché il ciclo è due volte più veloce di c nei miei programmi semplici?

Ho effettuato una misstake cruciale nel programma? O il compilatore di MinGW è mal configurato o qualcosa del genere?

public class Jrand { 

public static void main (String[] args) { 

    long startTime = System.currentTimeMillis(); 
    int i; 
    for (i = 0; i < 2000000000; i++) { 
     // Do nothing! 
    } 
    long endTime = System.currentTimeMillis(); 
    float totalTime = (endTime - startTime); 

    System.out.println("time: " + totalTime/1000); 
} 

} 

IL C-PROGRAMMA

#include<stdio.h> 
#include<stdlib.h> 
#include <time.h> 
int main() { 

    clock_t startTime; 
    startTime = clock(); 

    int i; 
    for (i = 0; i <= 2000000000; i++) { 
     // Do nothing 
    } 
    clock_t endTime; 
    endTime = clock(); 

    float totalTime = endTime - startTime; 
    printf("%f", totalTime/1000); 

    return 0; 
} 
+3

Il il ciclo è probabilmente ignorato in Java. Prova a fare qualcosa di significativo nel ciclo, come aggiornare una somma e stamparla dopo il ciclo. Si veda anche [questa discussione] (http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java) –

+4

Optimizer. Come disse Sanjay. – Devolus

+11

Hai attivato le ottimizzazioni per la compilazione C?Probabilmente non l'hai fatto perché altrimenti il ​​tuo codice C dovrebbe tornare a 0 secondi. – Mysticial

risposta

21

Ricostruisci la versione C con qualsiasi livello di ottimizzazione diverso da -O0 (ad esempio -O2) e troverai che viene eseguito in 0 secondi. Quindi la versione di Java impiega 1,6 secondi per non fare nulla, e la versione C impiega 0,0 secondi (in realtà, circa 0,00005 secondi) per non fare nulla.

+7

Forse sul suo sistema. Nella * prima esecuzione * del mio vecchio laptop (Core 2 Duo) la versione di Java impiega 0,059 secondi ... È solo l'ora di avvio della JVM, probabilmente l'IO del disco. Nel caso ci siano dei basher Java qui. –

+0

grazie! Ho usato -O2 e aggiunto un semplice calcolo. all'interno del ciclo. linguaggio c: 0,0000 ... secondi. Java: 6,7 secondi. Potrebbe anche quest'ultimo essere ottimizzato? –

+0

@owlstead: 0,059 secondi di sovraccarico all'avvio sono un motivo in più per colpire ancora Java. È più lungo del framtime per i framerate/refresh rate tipici. –

10

Java è più aggressivo ad eliminare il codice che non fa nulla. È meno probabile che lo sviluppatore sappia cosa stanno facendo. Non stai cronometrando il ciclo ma quanto tempo impiega java per rilevare ed eliminare il ciclo.

In breve, Java è spesso più veloce nel non fare nulla di utile.

Inoltre, se si ottimizza il codice C e si rimuovono le informazioni di debug, verrà eseguita la stessa operazione, molto probabilmente più breve.

+6

Qualsiasi compilatore C decente non genererà alcun codice per il ciclo inutile a meno che non si compili intenzionalmente con l'ottimizzazione disabilitata, che è uno strumento per il single-step del programma e la capacità di comprendere il flusso della macchina astratta . –

1

Se volete punto di riferimento questo, invece di fare nulla, cerca di qualcosa di utile come il calcolo qualcosa su ogni iterazioni. Ad es. conta i loop in qualche altra variabile e assicurati di usarlo alla fine (stampandolo per e.g), in modo che non venga ottimizzato.

semplici test alternativi potrebbero accederanno un array lineare (solo lettura), copiare elementi da un array all'altro (lettura e scrittura), o fare alcune operazioni sui dati. Alcuni di questi casi potrebbe essere interessante come si aprono diverse ottimizzazioni del compilatore molto semplici che in seguito sarà possibile vedere nel risultato binario/bytecode, come ad esempio svolgimento del ciclo, l'allocazione dei registri, e roba forse ancora più complicato come vettorializzazione o il movimento di codice. Java dall'altra può impiegare alcuni trucchi più maliziose, come jitting (ricompilando dinamicamente al volo)

L'ambito di ottimizzazione del compilatore è enorme, hai appena incontrato il più fondamentale - l'eliminazione del codice inutile :)