Pergunta

Meu professor fez um benchmark informal em um pequeno programa e os tempos do Java foram:1,7 segundos para a primeira corrida e 0,8 segundos para as corridas seguintes.

  • Isso se deve inteiramente ao carregamento do ambiente de execução no ambiente operacional?

    OU

  • É influenciado pela otimização do código pelo Java e pelo armazenamento dos resultados dessas otimizações (desculpe, não conheço o termo técnico para isso)?

Foi útil?

Solução

Concordo que a diferença de desempenho vista pelo autor da postagem é provavelmente causada pela latência do disco que traz o JRE para a memória.O compilador Just In Time (JIT) não teria impacto no desempenho de uma pequena aplicação.

Java 1.6u10 (http://download.java.net/jdk6/) toca os JARs de tempo de execução em um processo em segundo plano (mesmo que o Java não esteja em execução) para manter os dados no cache do disco.Isso diminui significativamente o tempo de inicialização (o que é um grande benefício para aplicativos de desktop, mas provavelmente de valor marginal para aplicativos do lado do servidor).

Em aplicações grandes e de longa execução, o JIT faz uma grande diferença ao longo do tempo - mas a quantidade de tempo necessária para o JIT acumular estatísticas suficientes para iniciar e otimizar (5 a 10 segundos) é muito, muito curta em comparação com a vida geral do aplicativo (a maioria é executada por meses e meses).Embora armazenar e restaurar os resultados do JIT seja um exercício acadêmico interessante, a melhoria prática não é muito grande (é por isso que a equipe do JIT tem se concentrado mais em coisas como estratégias de GC para minimizar perdas de cache de memória, etc...).

A pré-compilação das classes de tempo de execução ajuda bastante os aplicativos de desktop (assim como o pré-carregamento do cache de disco 6u10 mencionado acima).

Outras dicas

Ok, encontrei onde li isso.Tudo isso vem de "Aprendendo Java" (O'Reilly 2005):

O problema com uma compilação JIT tradicional é que a otimização do código leva tempo.Portanto, um compilador JIT pode produzir resultados decentes, mas pode sofrer uma latência significativa quando o aplicativo é inicializado.Geralmente, isso não é um problema para aplicativos de longa duração no servidor, mas é um problema sério para software e aplicativos do lado do cliente executados em dispositivos menores com recursos limitados.Para resolver isso, a tecnologia de compilador da Sun, chamada HotSpot, usa um truque chamado compilação adaptativa.Se você observar o que os programas realmente gastam seu tempo fazendo, verá que eles gastam quase todo o tempo executando uma parte relativamente pequena do código repetidas vezes.O pedaço de código executado repetidamente pode representar apenas uma pequena fração do programa total, mas seu comportamento determina o desempenho geral do programa.A compilação adaptativa também permite que o tempo de execução Java aproveite novos tipos de otimizações que simplesmente não podem ser feitas em uma linguagem compilada estaticamente, daí a afirmação de que o código Java pode ser executado mais rápido que C/C++ em alguns casos.

Para aproveitar esse fato, o HotSpot começa como um interpretador de bytecode Java normal, mas com uma diferença:ele mede (perfilia) o código durante a execução para ver quais partes estão sendo executadas repetidamente.Depois de saber quais partes do código são cruciais para o desempenho, o HotSpot compila essas seções em um código de máquina nativo ideal.Como ele compila apenas uma pequena parte do programa em código de máquina, ele pode gastar o tempo necessário para otimizar essas partes.O resto do programa pode não precisar ser compilado – apenas interpretado – economizando memória e tempo.Na verdade, o Java VM padrão da Sun pode ser executado em um dos dois modos:cliente e servidor, que informam se deve enfatizar o tempo de inicialização rápido e a conservação de memória ou o desempenho máximo.

Uma pergunta natural a ser feita neste momento é: Por que jogar fora todas essas boas informações de criação de perfil sempre que um aplicativo é encerrado?Bem, a Sun abordou parcialmente esse tópico com o lançamento do Java 5.0 por meio do uso de classes compartilhadas somente leitura que são armazenadas persistentemente em um formato otimizado.Isso reduz significativamente o tempo de inicialização e a sobrecarga de execução de muitos aplicativos Java em uma determinada máquina.A tecnologia para fazer isso é complexa, mas a ideia é simples:otimize as partes do programa que precisam ser executadas rapidamente e não se preocupe com o resto.

Estou me perguntando até que ponto a Sun chegou desde o Java 5.0.

Não tenho conhecimento de nenhuma máquina virtual de uso generalizado que salve dados estatísticos de uso entre invocações de programas - mas certamente é uma possibilidade interessante para pesquisas futuras.

O que você está vendo é quase certamente devido ao cache do disco.

Concordo que provavelmente é o resultado do cache de disco.

Para sua informação, o IBM Java 6 VM contém um compilador antecipado (AOT).O código não é tão otimizado quanto o JIT produziria, mas é armazenado em VMs, acredito em algum tipo de memória compartilhada persistente.Seu principal benefício é melhorar o desempenho da inicialização.O IBM VM, por padrão, JITs um método depois de ter sido chamado 1000 vezes.Se ele souber que um método será chamado 1000 vezes apenas durante a inicialização da VM (pense em um método comumente usado como java.lang.String.equals(...) ), então é benéfico armazená-lo no cache AOT para que ele nunca perca tempo compilando em tempo de execução.

Você deve descrever como foi feito o seu Benchmark.Principalmente nesse ponto que você começa a medir o tempo.

Se você incluir o tempo de inicialização da JVM (que é útil para avaliar a experiência do usuário, mas não tão útil para otimizar o código Java), pode ser um efeito de cache do sistema de arquivos ou pode ser causado por um recurso chamado "Compartilhamento de dados de classe Java":

Para Sol:

http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html

Esta é uma opção onde a JVM salva uma imagem preparada das classes de tempo de execução em um arquivo, para permitir carregamento (e compartilhamento) mais rápido delas na próxima inicialização.Você pode controlar isso com -Xshare:on ou -Xshare:off com uma Sun JVM.O padrão é -Xshare:auto que carregará a imagem das classes compartilhadas, se presente, e se não estiver presente, irá gravá-la na primeira inicialização se o diretório for gravável.

Com o IBM Java 5, isso é ainda mais poderoso:

http://www.ibm.com/developerworks/java/library/j-ibmjava4/

Não conheço nenhuma JVM convencional que esteja salvando estatísticas JIT.

Java JVM (na verdade, pode mudar de diferentes implementações da JVM), quando iniciado pela primeira vez, interpretará o código de bytes.Uma vez que detecta que o código estará sendo executado um número suficiente de vezes, ele é JIT para a linguagem de máquina nativa para que ele seja executado mais rapidamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top