Por que os idiomas da VM não são compilados apenas uma vez?

8

(Antes de tudo, devo deixar claro que compiladores e máquinas virtuais ( aka ) são um campo completamente desconhecido para mim)

Pelo que entendi, toda vez que um aplicativo Java / C # / ... é executado, uma VM é chamada e converte o código intermediário (bytecode, CIL, etc) nas instruções da máquina.

Mas por que essa operação não pode ser executada apenas uma vez - no momento da instalação?

vemv
fonte
1
O que é o tempo de instalação?
Peter Taylor
3
Não tenho certeza se é um termo padrão, mas eu quis dizer: quando o usuário instala o programa - executa-o pela primeira vez -, em vez de compilar um programa na máquina do desenvolvedor (quem não conhece a plataforma que um determinado usuário usará - e você não deseja distribuir um instalador por plataforma).
vemv
@vemv compilação em tempo de execução permite que o VM se especializar as instruções de máquina para seu hardware específico
Lucina

Respostas:

8

No caso de Java, a JVM pode fazer otimizações que cruzam os limites da biblioteca. Por exemplo, você pode incorporar um método de uma biblioteca em seu próprio código de cliente. Este tipo de otimização não pôde ser feito em tempo de compilação, porque a biblioteca pode mudar antes da execução. É perfeitamente possível que seu libfoo-1.0 seja substituído pelo libfoo-1.1 sem uma recompilação. Se isso acontecer, as linhas de biblioteca cruzadas feitas em tempo de compilação se tornarão totalmente inválidas.

Ao fazer a otimização apenas em tempo de execução, não há preocupação de que a biblioteca que está sendo alterada sob você invalide as otimizações.

Steven Schlansker
fonte
1
Uma linha poderia ser em vez de gerar código de máquina para chamar um "Y.setX (x)" (onde Y é de uma biblioteca de terceiros) que executa "this.x = x" e, em seguida, gerar código de máquina para "Yx = x "
Em resumo, o tempo de execução possui informações que o tempo de compilação não possui.
precisa
6

Porque isso os impede de usar muitos recursos. Por exemplo, como o JIT pode gerar novas instanciações genéricas de DLLs carregadas em tempo de execução? Essas DLLs não existem no momento da instalação.

DeadMG
fonte
1
Felicidades pela resposta. Acho que entendi o problema da instanciação - não posso ter 100% de certeza, porque sua resposta é um pouco sucinta. Também listar outros recursos indisponíveis tornaria seu ponto mais forte.
vemv
3
Ou, em geral: um JIT pode fazer otimizações com base na entrada; DLLs carregadas em tempo de execução são um tipo de entrada.
quer
1
Obviamente, essas DLL são instalados, bem como, e cada DLL poderia ser compilado em seu tempo de instalação. Você perde otimizações entre módulos, mas essas são um pouco teóricas de qualquer maneira.
MSalters
@ MSalters: nem toda DLL tem um tempo de "instalação".
DeadMG
@DeadMG: Estamos discutindo sobre sistemas hipotéticos de qualquer maneira; esse sistema pode facilmente exigir instalação. (Além disso, seria um benefício de segurança se a introdução do código executável fosse explicitamente gerenciada).
MSalters 1/11/11
5

Pode e costuma ser, pelo menos com aplicativos .NET. Consulte Gerador de imagens nativas

uma ferramenta que melhora o desempenho de aplicativos gerenciados. Ngen.exe cria imagens nativas, que são arquivos que contêm código de máquina específico do processador compilado, e as instala no cache de imagens nativas no computador local. O tempo de execução pode usar imagens nativas do cache em vez de usar o compilador just-in-time (JIT) para compilar o assembly original ...

Nemanja Trifunovic
fonte
Note-se que esta é também semelhante ao Runtime Android (ART) construído pelo Google para melhorar o desempenho de apps Android
neelsg
3

Para reformular a pergunta de acordo com o esclarecimento:

Por que o bytecode não pode ser compilado em código nativo na primeira vez em que o programa é executado?

Eu vejo os seguintes problemas:

  • Onde os resultados seriam armazenados? Você não pode assumir que o arquivo que contém o bytecode é gravável; você não deseja inchar a máquina de um desenvolvedor despejando um novo .exe no armazenamento permanente toda vez que ele executa um teste; e se você armazenar o arquivo em armazenamento temporário, ele será perdido na próxima vez que você reiniciar, para não ganhar muito.

  • Você está trocando uma inicialização um pouco lenta todas as vezes por uma inicialização muito lenta na primeira vez. Não vai deixar uma ótima impressão com o cliente.

  • Você terá problemas significativos com o carregamento dinâmico de classes.

Peter Taylor
fonte
2
O primeiro ponto é trivial. Os caches são muito bem compreendidos. Quando o bytecode executável subjacente é removido, você pode excluir a entrada de cache associada e também se não for executada por muito tempo. Quanto ao segundo ponto, você pode fazer a compilação de métodos não utilizados em um encadeamento em segundo plano. Isso não deve prejudicar o tempo de inicialização, em que você compila os métodos chamados em primeiro plano.
MSalters
Até onde eu entendi, a pergunta não é sobre compilar na primeira execução, mas compilar na instalação.
Nemanja Trifunovic
@NemanjaTrifunovic, leia os comentários sobre a pergunta.
Peter Taylor
1
Receio não me explicar bem, desculpe. Eu quis dizer a primeira vez que um aplicativo é sempre executado, em seguida, seria necessário mais nenhum outro compilações. Assim como quando você precisa compilar um programa C antes de usá-lo no Linux.
vemv
1
Eu acho que isso conta como uma instalação - esses processos de compilação / compilação já estão em script para você.
vemv