un. Come si confronta oggi la velocità di Java con il C ++?
Difficile da misurare. Vale la pena notare che una parte importante della velocità di un'implementazione, l'allocatore di memoria, sono algoritmi molto diversi in Java e C ++. La natura non deterministica del collector rende estremamente difficile ottenere dati significativi sulle prestazioni rispetto alla gestione deterministica della memoria del C ++, perché non si può mai essere certi dello stato in cui si trova il collector. Ciò significa che è molto difficile scrivere un benchmark che potrebbe confrontarli significativamente. Alcuni schemi di allocazione della memoria funzionano molto più velocemente con un GC, altri molto più velocemente con un allocatore nativo.
Quello che vorrei dire, tuttavia, è che il GC Java deve funzionare velocemente in ogni situazione. Un allocatore nativo, tuttavia, può essere sostituito con uno più appropriato. Di recente ho posto una domanda su SO sul perché un C # Dictionary
potrebbe essere eseguito (0,45 ms sulla mia macchina) rispetto a un equivalentestd::unordered_map
quale eseguito su (10ms sulla mia macchina). Tuttavia, semplicemente sostituendo l'allocatore e l'haher con altri più appropriati, ho ridotto il tempo di esecuzione a 0,34 ms sulla mia macchina, un trentesimo del tempo di esecuzione originale. Non potresti mai e poi mai sperare di eseguire quel tipo di ottimizzazione personalizzata con Java. Un eccellente esempio di dove questo può fare davvero la differenza è il threading. Le librerie di thread nativi come TBB forniscono allocatori di memorizzazione nella cache dei thread che sono enormemente più veloci rispetto agli allocatori tradizionali quando gestiscono molte allocazioni su molti thread.
Ora, molte persone parleranno dei miglioramenti della JIT e di come la JIT abbia più informazioni. Certo, è vero. Ma non è nemmeno lontanamente vicino a ciò che un compilatore C ++ può estrarre, perché il compilatore ha, comparativamente, tempo e spazio infiniti in cui eseguire, dal punto di vista del tempo di esecuzione del programma finale. Ogni ciclo e ogni byte che la JIT spende pensando al modo migliore per ottimizzare il programma è un ciclo che il programma non sta spendendo in esecuzione e non può utilizzare per le proprie esigenze di memoria.
Inoltre, ci saranno sempre momenti in cui le ottimizzazioni di compilatore e JIT non possono dimostrare determinate ottimizzazioni, specialmente nel caso di analisi di escape. In C ++, quindi, poiché il valore è comunque nello stack , il compilatore non deve eseguirlo. Inoltre, ci sono cose semplici, come la memoria contigua. Se si alloca un array in C ++, si alloca un singolo array contiguo. Se si alloca un array in Java, allora non è affatto contiguo, poiché l'array è pieno solo di puntatori che potrebbero puntare ovunque. Questo non è solo un overhead di memoria e tempo per le doppie indirette, ma anche overhead della cache. Questo genere di cose è dove la semantica del linguaggio di Java impone semplicemente che deve essere più lenta del codice C ++ equivalente.
In definitiva, la mia esperienza personale è che Java potrebbe essere in media circa la metà della velocità di C ++. Tuttavia, non è realisticamente possibile eseguire il backup delle dichiarazioni di prestazione senza una suite di benchmark estremamente completa, a causa degli algoritmi fondamentalmente diversi coinvolti.
b. Sarebbe possibile creare un moderno titolo AAA usando Java?
Presumo che tu intenda "gioco", qui, e non una possibilità. In primo luogo, dovresti scrivere tutto da zero poiché quasi tutte le librerie e l'infrastruttura esistenti sono destinate al C ++. Pur non rendendolo impossibile di per sé, potrebbe certamente contribuire in modo solido a diventare irrealizzabile. In secondo luogo, anche i motori C ++ riescono a malapena a adattarsi ai piccoli vincoli di memoria delle console esistenti, se esistono anche JVM per quelle console, e i giocatori PC si aspettano un po 'di più dalla loro memoria. La creazione di giochi AAA performanti è abbastanza difficile in C ++, non vedo come si possa ottenere in Java. Nessuno ha mai scritto un gioco AAA con un tempo significativo trascorso in un linguaggio non compilato. Inoltre, sarebbe semplicemente soggetto a errori. La distruzione deterministica è essenziale quando si tratta, ad esempio, di risorse GPU e in Java,
c. In quali aree, in particolare, Java è più lento di C ++, se non del tutto? (ad es. scricchiolio del numero, grafica o semplicemente tutto intorno)
Ritornerei sicuramente per tutto. La natura di riferimento forzato di tutti gli oggetti Java significa che Java ha molti più riferimenti indiretti e riferimenti rispetto a C ++, un esempio che ho fornito in precedenza con gli array, ma si applica anche a tutti gli oggetti membri, ad esempio. Laddove un compilatore C ++ può cercare una variabile membro in tempo costante, un runtime Java deve seguire un altro puntatore. Più accessi fai, più lento sarà, e JIT non può farci nulla.
Laddove il C ++ può liberare e riutilizzare un pezzo di memoria quasi all'istante, in Java devi attendere la raccolta e spero che quel pezzo non sia andato via dalla cache e che intrinsecamente richiedere più memoria significa ridurre le prestazioni di paging e cache. Quindi guarda la semantica per cose come boxe e unboxing. In Java, se si desidera fare riferimento a un int, è necessario allocarlo in modo dinamico. Questo è uno spreco intrinseco rispetto alla semantica C ++.
Quindi hai il problema generici. In Java, è possibile operare su oggetti generici solo tramite l'ereditarietà di runtime. In C ++, i template hanno letteralmente zero overhead, qualcosa che Java non può eguagliare. Ciò significa che tutto il codice generico in Java è intrinsecamente più lento di un equivalente generico in C ++.
E poi vieni al comportamento indefinito. Tutti lo odiano quando il loro programma mostra UB e tutti desiderano che non esistesse. Tuttavia, UB abilita fondamentalmente ottimizzazioni che non possono mai esistere in Java. Dai un'occhiata a questo post che descrive le ottimizzazioni basate su UB. Non definire il comportamento significa che le implementazioni possono fare più ottimizzazioni e ridurre il codice richiesto per verificare le condizioni che sarebbero indefinite in C ++ ma definite in Java.
Fondamentalmente, la semantica di Java impone che sia un linguaggio più lento del C ++.
Java è ora considerato un linguaggio compilato o interpretato?
Non si adatta davvero a nessuno di questi gruppi. Direi che il gestito è davvero una categoria separata da solo, anche se direi che è decisamente più simile a un linguaggio interpretato che a un linguaggio compilato. Ancora più importante, ci sono praticamente solo due principali sistemi gestiti, JVM e CLR, e quando dici "gestito" è sufficientemente esplicito.
Quali sono le principali carenze di Java che sono state affrontate sin dai primi giorni?
La boxe automatica e il unboxing sono l'unica cosa che conosco. I generici risolvono alcuni problemi, ma tutt'altro che molti.
Quali sono alcune importanti carenze di Java che devono ancora essere risolte?
I loro generici sono molto, molto deboli. I generici di C # sono considerevolmente più potenti, anche se ovviamente non lo sono nemmeno i modelli. La distruzione deterministica è un'altra grave mancanza. Qualsiasi forma di lambda / chiusura è anche un grosso problema: puoi dimenticare un'API funzionale in Java. E, naturalmente, c'è sempre il problema delle prestazioni, per quelle aree che ne hanno bisogno.