Estou programando há alguns anos e comecei em Java, e no meu tempo encontrei muitas fontes diferentes alegando que o Java era uma linguagem inferior de uma maneira ou de outra. Estou ciente de que cada linguagem tem seus pontos fortes e fracos, mas muitas coisas que li sobre Java parecem datadas.
A razão mais citada para o Java ser inferior é o fato de ser muito mais lento que outras linguagens compiladas nativamente, como o C ++, por exemplo. Muitas pessoas criticam o designer de jogos Notch (que desenvolveu o Minecraft) por usar Java por causa de sua aparente falta no departamento de desempenho. Eu sei que o Java estava muito mais lento na época, mas houve muitas melhorias desde então, especialmente a compilação JIT.
Eu gostaria de obter algumas opiniões objetivas do Java como uma linguagem hoje. Então, minha pergunta tem 4 partes.
Atuação.
uma. Como a velocidade do Java hoje se compara ao C ++?
b. Seria possível criar um título AAA moderno usando Java?
c. Em que áreas, especificamente, o Java é mais lento que o C ++? (ou seja, processamento de números, gráficos ou apenas ao redor)
O Java agora é considerado uma linguagem compilada ou interpretada?
Quais são algumas das principais falhas do Java que foram tratadas desde os primeiros dias?
Quais são algumas das principais deficiências do Java que ainda precisam ser abordadas?
Editar:
Apenas para fins de esclarecimento, não estou fazendo esse Java vs C ++, obviamente, em média, o c ++ será um pouco mais rápido que o Java. Eu simplesmente preciso de algo para comparar o Java em termos de maturidade como uma linguagem neste momento. Como o c ++ existe desde sempre, pensei que seria um bom ponto de comparação.
fonte
Respostas:
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.
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ê
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 ++.
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.
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.
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.
fonte
Começarei com a condição de que é quase impossível alguém dar uma opinião verdadeiramente neutra sobre linguagens de programação. Se você conhece dois idiomas o suficiente para comentá-los de maneira significativa, é quase inevitável que você prefira um sobre o outro. Como aviso justo, prefiro C ++ em vez de Java, que sem dúvida influencia meus comentários em pelo menos algum grau.
1a. Velocidade: a velocidade que você obtém do C ++ ou do Java geralmente depende menos da linguagem ou de sua implementação do que da habilidade do (s) programador (es) que a utilizam. Por fim, o C ++ provavelmente pode ganhar velocidade mais frequentemente do que não, mas as diferenças no código que você escreve são o que realmente importa.
1b. Sim provavelmente. Ao mesmo tempo, o C ++ já está bem estabelecido, e duvido que a maioria dos estúdios de jogos veja vantagens suficientes para mudar para Java.
1c. Uma resposta completa para isso provavelmente pode preencher um grande volume. O C ++ geralmente se sai melhor com recursos mais limitados. O Java se beneficia mais de (por exemplo) ter muita memória "reserva" disponível.
2. Execução lenta e coleta lenta de lixo provavelmente seriam as duas mais óbvias. A biblioteca de janelas iniciais (AWT) foi bastante desajeitada - o Swing foi uma grande melhoria.
3. Verbosidade. Falta de sobrecarga do operador. Uso de coleta de lixo. Falta de herança múltipla. Os Java Generics são extremamente limitados em comparação aos modelos C ++.
Devo acrescentar que algumas (todas?) Dessas desvantagens (especialmente o uso de coleta de lixo, mas outras também) são vistas por muitas como vantagens do Java. A única exceção possível seria sua verbosidade. A situação da verbosidade está melhorando um pouco lentamente, mas você certamente não vê concursos de golfe com códigos vencedores do Java com muita frequência e, no código comum, tende a usar bastante código também. Eu suspeito que existem pelo menos alguns que o consideram mais legível e compreensível, então provavelmente também pode ser visto como uma vantagem.
fonte
fonte
Em primeiro lugar, em algum contexto, meu C ++ é muito enferrujado, portanto, a maioria das minhas experiências com Java se relaciona à minha experiência mais recente com C #, que é uma comparação muito maior entre maçãs e maçãs.
1. Speed
Eu acho que isso é melhor respondido pela pergunta SO Por que o java tinha a reputação de ser lento? mas também acho que toda essa questão é colorida pelo post de Jeff Atwood no blog, Gorilla vs. Shark . Agradecimentos a Péter & Christopher.
Isso depende das prioridades dos desenvolvedores e das habilidades dos desenvolvedores. Além disso, não é uma situação de ou / ou, partes diferentes do título podem exigir coisas diferentes da linguagem em que são implementadas, levando a um ambiente de linguagem heterogêneo.
Vi vários jogos recentemente mencionando que eles carregam um ambiente Python enquanto carregam, e suspeito que cavalos para cursos é uma forte motivação se você deseja obter seu título a tempo para a temporada de férias (por exemplo) .
Você pode escrever código com baixo desempenho em qualquer idioma, mas alguns idiomas facilitam a fazer boas escolhas, enquanto outros são mais propensos a se deixar levar por sua própria petarda . Java se enquadra na categoria anterior, C ++ definitivamente se enquadra na última.
Com grande poder, vem uma grande responsabilidade, como eles dizem (para não mencionar a capacidade de estragar completamente sua pilha * 8 ').
2. O Java agora é considerado uma linguagem compilada ou interpretada?
Não sei dizer o que a maioria das pessoas considera, mas muitas pessoas sabem a diferença entre linguagens compiladas e interpretadas, e não viviam em uma caverna nos últimos 20 anos, também saberiam que o JIT ( Just-in O compilador -Time ) é uma parte importante do ecossistema Java; portanto, provavelmente é mais provável que seja considerado compilado atualmente.
3. Quais são algumas das principais falhas do Java que foram tratadas desde os primeiros dias?
Sou um recém-convertido para Java, por isso tenho pouco contexto sobre como ele evoluiu. Mas é interessante notar que existem livros como Java: The Good Parts que procuram orientar as pessoas na direção das partes da linguagem que devem ser preferidas atualmente e afastar as pessoas das áreas que são, ou deveriam ser, descontinuada.
4. Quais são algumas das principais deficiências do Java que ainda precisam ser abordadas?
Na minha opinião, um problema com Java tem sido a lenta adoção de novos recursos.
Tendo chegado ao Java a partir de C # e olhando através da página de comparação da Wikipedia , estas são as coisas que mais se destacam para mim:
Coisas que sinto falta em Java, em comparação com C #
Encerramentos / lambdas . Fiquei realmente decepcionado quando soube que o suporte a Java estava sendo adiado novamente .Finalmente, temos Closures / lambdas no Java 8, mas o tempo que levou atestou minha declaração sobre a adoção lenta.var
) pode parecer um açúcar sintático, mas quando você tem tipos genéricos complexos, pode tornar o código muito mais claro, removendo muitas duplicações inúteis.struct
em uma classe completa.Coisas que não sinto falta em Java, em comparação com C #
unsafe
código. Você tem que ser tão cuidadoso com isso que raramente acho que vale a pena o esforço extra.Como tal, mesmo ao comparar maçãs com maçãs, considera-se que Java ficou para trás.
Os outros dois grandes problemas que vejo no Java são o atraso flagrante de inicialização e o fato de que (para algumas JVMs) você precisa microgerenciar seu heap e até o heap de geração permanente . Com os aplicativos C # sempre iniciados imediatamente, e eu nunca tive que pensar em heap, pois ele foi alocado para fora do pool de memória do sistema, não para um pool pré-alocado atribuído à máquina virtual.
fonte
Posso apontar uma fonte que pode ajudar a responder a primeira parte da sua pergunta. Linguagens de programação disparam http://shootout.alioth.debian.org/u64q/which-programming-languages-are-fastest.php é uma fonte muito boa para ver a rapidez com que as linguagens se comparam. Eles podem até ser filtrados em diferentes categorias para ver em quais áreas as linguagens se saem melhor do que outras. O Java é muito mais rápido do que era há vários anos.
fonte
1) Estritamente falando sobre o UX que recebo com Java, parece lento. Eu não posso te dizer por que realmente. Ainda tenho que encontrar um aplicativo de desktop baseado em Java, que não parece lento e tem uma alternativa não-Java mais rápida. Dito isto, o Java pode ser muito rápido em pura velocidade computacional e a Internet está cheia de referências para provar isso. No entanto, o tempo de inicialização dos aplicativos Java e a capacidade de resposta de suas GUIs ainda precisam melhorar o IMHO. Talvez você possa fazer isso;)
No final, a velocidade não é um problema. Não apenas o hardware está ficando cada vez mais rápido, como também a maioria das pessoas ainda se importa surpreendentemente pouco com o software, o que deve fazer e a proporção de tempo gasto interagindo versus tempo gasto em espera é razoável.
2) Essa distinção tornou-se tão embaçada ultimamente, que há muito pouco valor nela.
3 + 4) Houve algumas mudanças no Java, na verdade. Algumas pessoas já argumentam que essas mudanças mancharam a filosofia puramente simplista de Java, apostando em características alienígenas. É realmente difícil dizer objetivamente, o que é uma falha e o que é uma força. Para mim, Java é desnecessariamente detalhado, restritivo e pobre em recursos, enquanto outras pessoas consideram essas mesmas características como uma agradável ambiguidade, segurança e clareza.
Portanto, embora sejam essas coisas que pessoalmente me façam não usar Java, não acho que simplesmente adicionar as coisas que sinto falta em Java seja uma boa idéia. Há muitas linguagens que eu gosto de rodar na JVM e dobrar o Java para estar mais perto delas, apenas anulando o objetivo do Java.
É uma questão de preferência
O problema com o Java é que ele foi projetado para impedir que você atire no próprio pé. Uma causa nobre, mas com todas as restrições que ela impõe a você, não é improvável que você tropece em um dos seus pés seguros, não consiga se apoiar com as mãos amarradas nas costas para sua própria segurança e, finalmente, morra, porque você quebra seu crânio. : D
De certa forma, o Java foi uma resposta ao C ++, que fornece corda suficiente para você não apenas se enforcar, mas também o resto do mundo. É toda essa corda, o que a torna tão atraente para os cowboys. Toda essa liberdade e todo esse poder.
Simplificando, isso é realmente apenas uma questão de preferência.
Mas, um ponto é que, com o C ++ como alternativa ao Java, você pode escolher suas próprias restrições. Ou realmente enlouquecer com todo o controle que você tem, arriscando confundir totalmente seus colegas:
Java optou por não oferecer sobrecarga de operador, por esse mesmo motivo. Obviamente, isso impede que as pessoas ofuscem seu código multiplicando os ponteiros de função com as listas. Mas, ao mesmo tempo, impede que outras pessoas realizem cálculos geométricos / algébricos com os operadores habituais.
(v1 * v2 / scale) + (v3 * m)
realmente é muito mais claro quev1.multiply(v2).divide(scale).add(v3.multiply(m))
. Entendo por que isso pode desencorajar as pessoas que lidam com gráficos e cálculos 3D.Java optou por impor a coleta de lixo, enquanto em C ++ você pode escolher. Você pode realmente cavar todo o caminho e se aproximar do hardware. Você pode compactar dados densamente em estruturas. Você pode executar magia negra, como a raiz quadrada inversa rápida . Você pode executar algumas das metaprogramas mais complicados e enigmáticos da Terra usando modelos. Mas também significa que você pode se perder e passar horas depurando toda a bagunça criada ou examinando erros de compilador absolutamente inúteis.
Mas se você tiver a disciplina de usar apenas as partes da linguagem que realmente domina, poderá escrever o código C ++ com a mesma segurança do código Java, mas terá a opção de avançar gradualmente.
Portanto, embora tecnicamente nada impeça você de escrever software de ponta com Java, você descobrirá que muitos desenvolvedores são realmente apaixonados por escrever ótimos softwares e se divertir e evoluir enquanto fazem isso, indo além do que Java tem a oferecer como linguagem.
Mas o mundo não consiste apenas de pessoas estabelecidas não criar a próxima grande coisa , ou apenas de pessoas que irão restringir o uso do poder dado a eles apenas como medida em que controlá-lo. IMHO Java é a combinação perfeita para pessoas que desejam produzir resultados estáveis de maneira confortável.
fonte
Coleta de lixo é a grande coisa. De vez em quando, o GC bloqueia todo o resto por várias centenas de milissegundos (dependendo do tamanho da pilha) e faz uma grande coleta. Isso é bom se você não tiver restrições de tempo, mas se atrasar significa falha, isso é um impedimento de exibição. Você pode gastar o dinheiro em Java em tempo real e em um sistema operacional em tempo real, mas pode simplesmente usar o GCC e o Linux padrão e não terá esses problemas.
Sem as pausas aleatórias imprevisíveis, o Java provavelmente é rápido o suficiente para a maioria das coisas atualmente. E se você passar meses ajustando as configurações do GC e outras, talvez, apenas talvez, consiga que funcione por tempo suficiente para que o cliente faça um cheque.
fonte
3) Deficiências que foram corrigidas.
Alguns anos atrás, havia muita raiva de Java. A maioria dos programadores Java são programadores da Web / servidor e estavam enlouquecendo com a verbosidade do Java. Então, algumas linguagens como Ruby se tornaram populares e o Java começou a minguar. No entanto, com as novas anotações e estruturas como hibernate e Spring, as pessoas pararam de reclamar e voltaram ao Java.
4) Deficiências atuais
O hardware está todo multicore. Embora o Java possa executar multithread, ele é baseado em C, que é uma linguagem seqüencial e a funcionalidade para torná-lo multithread não é elegante, para dizer o mínimo. A propósito, isso não é apenas uma crítica ao Java, mas praticamente todas as linguagens. É necessária uma maneira completamente diferente de pensar sobre o código. Talvez a programação funcional seja o caminho do futuro.
fonte
Eu meio que reagi a essa pergunta, porque ela forneceria respostas enganosas e amplamente irrelevantes:
Todos podem concordar que seria difícil produzir títulos AAA usando Java e que não tenho exemplos reais que eu saiba. No entanto, dada a natureza do AAA que assumiria muitas coisas (já que é realmente um termo confuso vindo do marketing), é melhor perguntar o seguinte:
A resposta é " Sim, você pode ". No entanto, a parte do sucesso real da equação é mais baseada em sua persistência e sorte (ou adesão ao zeitgeist), mas que está fora do escopo deste site.
fonte
Uma área certian de velocidade se resume a compilador versus compilador. Não é idioma versus idioma. Pode haver vantagens na compilação JIT, pois ela pode otimizar as especificações da máquina em que está sendo executada. Compare C ++ compilado JIT vs Java para uma comparação mais compilador "maçãs com maçãs".
Mas há algumas coisas em que a própria linguagem Java limita seu próprio desempenho.
alocação na pilha. Java não pode fazer isso. Para pequenas classes de tamanho fixo em uma solução não recursiva, isso geralmente é ideal. Você também pode evitar a fragmentação de heap.
funções não virtuais. Java não pode fazer isso. Todas as chamadas de método recebem um acerto permanente, mesmo quando não estão planejadas para serem substituídas.
Provavelmente algumas outras coisas, mas é tudo o que consigo pensar do alto da minha cabeça.
fonte
1) irrelevante e argumentativo para inicializar.
Não apenas os principais softwares podem ser criados em Java, mas também são entregues todos os dias e administram a maioria das grandes empresas do mundo.
2) idem.
Leia a especificação da JVM e você sabe. Java nunca foi uma linguagem interpretada.
3) idem.
Leia os 15 anos de notas de lançamento. É impossível descobrirmos o que você considera "grandes falhas" a serem resolvidas.
4) idem.
A principal falha que precisa ser resolvida é o JCP, que é propenso a se intrometer na linguagem e nas bibliotecas principais por nenhuma outra razão aparente, a não ser colocar o nome de somoene em um JSR para que eles possam escrever um livro com uma sinopse oficial de que "eles eram os líder do JSR-666 ". Esperamos que a reestruturação da JCP pela Oracle cuide disso.
Você parece querer apenas provocar uma guerra de idiomas aqui e ter seu preconceito contra Java confirmado por outras pessoas, porque você não consegue encontrar nenhuma justificativa real para isso.
fonte