uma. Como a velocidade do Java hoje se compara ao C ++?
Difícil de medir. Vale a pena notar que grande parte da velocidade de uma implementação, seu alocador de memória, são algoritmos muito diferentes em Java e C ++. A natureza não determinística do coletor torna extremamente difícil obter dados significativos de desempenho em comparação com o gerenciamento determinístico de memória do C ++, porque você nunca pode ter certeza de qual estado o coletor está. Isso significa que é muito difícil escrever uma referência que possam compará-los significativamente. Alguns padrões de alocação de memória são executados muito mais rapidamente com um GC, outros são executados muito mais rapidamente com um alocador nativo.
O que eu diria, no entanto, é que o Java GC precisa executar rapidamente em todas as situações. Um alocador nativo, no entanto, pode ser trocado por outro mais apropriado. Recentemente, coloquei uma pergunta no SO sobre por que um C # Dictionary
poderia ser executado em (0,45 ms na minha máquina) comparado a um equivalentestd::unordered_map
que foi executado em (10ms na minha máquina). No entanto, simplesmente trocando o alocador e o hasher por outros mais apropriados, reduzi esse tempo de execução para 0,34 ms na minha máquina - um trigésimo do tempo de execução original. Você nunca poderia esperar executar esse tipo de otimização personalizada com Java. Um excelente exemplo de onde isso pode fazer uma diferença real é o encadeamento. Bibliotecas de encadeamentos nativas como TBB fornecem alocadores de cache de encadeamento que são massivamente mais rápidos que alocadores tradicionais ao lidar com muitas alocações em vários encadeamentos.
Agora, muitas pessoas falarão sobre melhorias no JIT e como o JIT tem mais informações. Claro, isso é verdade. Mas ainda não é nem remotamente parecido com o que um compilador C ++ pode obter - porque o compilador possui, comparativamente, tempo e espaço infinitos para executar, da perspectiva do tempo de execução do programa final. Cada ciclo e cada byte que o JIT gasta pensando na melhor forma de otimizar seu programa é um ciclo que seu programa não está gastando em execução e não pode usar para suas próprias necessidades de memória.
Além disso, sempre haverá momentos em que as otimizações do compilador e do JIT não podem provar certas otimizações - especialmente no caso de coisas como análise de escape. Em C ++, como o valor está na pilha de qualquer maneira , o compilador não precisa executá-lo. Além disso, existem coisas simples, como memória contígua. Se você alocar uma matriz em C ++, aloca uma única matriz contígua. Se você alocar uma matriz em Java, ela não é contígua, porque a matriz é preenchida apenas com ponteiros que podem apontar para qualquer lugar. Isso não é apenas uma sobrecarga de memória e tempo para as indiretas duplas, mas também de sobrecargas de cache. É nesse tipo de coisa que a semântica da linguagem do Java simplesmente impõe que ele deve ser mais lento que o código C ++ equivalente.
Por fim, minha experiência pessoal é que o Java pode ter cerca de metade da velocidade do C ++, em média. No entanto, não há realmente nenhuma maneira de fazer backup de nenhuma declaração de desempenho sem um conjunto de benchmarks extremamente abrangente, devido aos algoritmos fundamentalmente diferentes envolvidos.
b. Seria possível criar um título AAA moderno usando Java?
Presumo que você queira dizer "jogo", aqui, e não há chance. Em primeiro lugar, você teria que escrever tudo do zero, já que quase todas as bibliotecas e infraestrutura existentes têm como destino o C ++. Embora não o torne impossível por si só, certamente poderia contribuir solidamente para o inviável. Em segundo lugar, mesmo os mecanismos C ++ dificilmente se encaixam nas pequenas restrições de memória dos consoles existentes - se existirem JVMs para esses consoles - e os jogadores de PC esperam um pouco mais por sua memória. Criar jogos AAA de alto desempenho já é bastante difícil em C ++, não vejo como isso poderia ser alcançado em Java. Ninguém jamais escreveu um jogo AAA com um tempo significativo gasto em um idioma não compilado. Mais do que isso, seria extremamente propenso a erros. A destruição determinística é essencial ao lidar com, por exemplo, recursos da GPU - e em Java, você
c. Em que áreas, especificamente, o Java é mais lento que o C ++? (ou seja, processamento de números, gráficos ou apenas ao redor)
Eu definitivamente apostaria em tudo. A natureza de referência forçada de todos os objetos Java significa que o Java possui muito mais indiretos e referências do que o C ++ - um exemplo que eu dei anteriormente com matrizes, mas também se aplica a todos os objetos membros, por exemplo. Onde um compilador C ++ pode procurar uma variável de membro em tempo constante, um tempo de execução Java deve seguir outro ponteiro. Quanto mais acessos você fizer, mais lento ficará e não haverá nada que o JIT possa fazer a respeito.
Onde o C ++ pode liberar e reutilizar uma parte da memória quase instantaneamente, em Java, é necessário aguardar a coleta, e espero que a peça não tenha saído do cache, e, inerentemente, exigir mais memória significa menor desempenho do cache e da paginação. Então olhe para a semântica para coisas como boxe e unboxing. Em Java, se você deseja fazer referência a um int, é necessário alocá-lo dinamicamente. Isso é um desperdício inerente comparado à semântica do C ++.
Então você tem o problema de genéricos. Em Java, você pode operar apenas em objetos genéricos através da herança em tempo de execução. No C ++, os modelos têm literalmente zero sobrecarga - algo que o Java não pode corresponder. Isso significa que todo código genérico em Java é inerentemente mais lento que um equivalente genérico em C ++.
E então você chega ao comportamento indefinido. Todo mundo odeia quando seu programa exibe UB, e todo mundo deseja que ele não exista. No entanto, o UB permite fundamentalmente otimizações que nunca podem existir em Java. Dê uma olhada nesta postagem descrevendo otimizações baseadas no UB. Não definir comportamento significa que as implementações podem fazer mais otimizações e reduzir o código necessário para verificar condições que seriam indefinidas em C ++, mas definidas em Java.
Fundamentalmente, a semântica do Java determina que é uma linguagem mais lenta que o C ++.
O Java agora é considerado uma linguagem compilada ou interpretada?
Realmente não se encaixa em nenhum desses grupos. Eu diria que gerenciado é realmente uma categoria separada por si só, embora eu diria que é definitivamente mais como uma linguagem interpretada do que uma linguagem compilada. Mais importante, existem basicamente apenas dois principais sistemas gerenciados, a JVM e o CLR, e quando você diz "gerenciado", é suficientemente explícito.
Quais são algumas das principais falhas do Java que foram tratadas desde os primeiros dias?
Boxe e unboxing automáticos são a única coisa que eu sei. Os genéricos resolvem alguns problemas, mas estão longe de muitos.
Quais são algumas das principais deficiências do Java que ainda precisam ser abordadas?
Seus genéricos são muito, muito fracos. Os genéricos do C # são consideravelmente mais fortes - embora, é claro, também não sejam modelos. Destruição determinística é outra grande falta. Qualquer forma de lambda / encerramento também é um grande problema - você pode esquecer uma API funcional em Java. E, é claro, sempre há a questão do desempenho, para as áreas que precisam deles.