Bom, nesse caso não há muito o que uma linguagem de programação AOT possa fazer para competir com linguagens que usa JIT. Mas há casos e casos:
- Se seu programa precisa ser leve com pouco gasto de RAM e Memória: AOT
- Se seu programa for criado para iniciar super rápido e ser usado rapidamente: AOT
Em outros casos, não há problema nenhum em usar JIT sabendo que:
-
Apesar do aumento de performance, o JIT vai consumir mais cpu e memória para otimizar o seu código em execução
-
A inicialização de um processo com JIT é mais lento que a inicialização de um projeto AOT por conter estruturas adicionais para compilação in-runtime do projeto
Mas se seu código vai ficar por muito tempo vivo, de preferência continuamente executando alguma coisa então não tem nada de errado em usar JIT.
Inclusive o canal do Andreas Kling que eu citei em outro post, para lidar com o ladybird, seu webbrowser ele decidiu criar um interpretador javascript próprio chamado LibJS que contém um JIT próprio e você pode acompanhar por exemplo este Vídeo sobre ele prototipando um JIT
E voltando ao assunto principal, não tem com uma linguagem AOT competir com um JIT porque as abordagens são diferentes:
AOT: Passei uma vez pelo código e o binário vai ser justamente isso aqui x. JIT: Tive que passar várias vezes pelo mesmo trecho de código então acho que posso otimizar isso aqui x.
AOT: Passei uma vez pelo código e o binário vai ser justamente isso aqui x. JIT: Tive que passar várias vezes pelo mesmo trecho de código então acho que posso otimizar isso aqui x.
Valeu pelas dicas, vou assistir. Eu vejo o trade-off assim:
AOT: Não vai perder tempo durante o run-time compilando nada. Não precisa esquentar (warmup). JIT: Vai perder tempo durante o run-time compilando os hot spots. Vai precisar de um tempo de warmup para peak performance.
Só que o JIT pode fazer otimizações muito mais agressivas que o AOT. Acho que o pessoal sempre achou que AOT com -O3 era a coisa mais rápida do mundo. Pelo testes que eu venho fazendo aí parece que perde muitas vezes para o JIT. Runtime information ajuda muito nas otimizações mais agressivas, principalmente no inlining. Sem saber os hotspots, o AOT vai acabar deixando de fazer inlining nas coisas mais importantes. Uma idéia que pensei aqui: por que os compiiladores de C++ não possuem alguma diretriz para forçar inlining de algum método no matter what? Ou tem isso e eu desconheço?
O que se faz é usar PGO (profiling information) that can be fed into the AOT compiler. Tanto o AOT quanto o JIT podem ter isso. Mas daí o JIT leva muita vantagem, porque se os HotSpots mudarem em tempo de execução ele pode se re-adaptar, ou seja, recompilar os novos hot spots. AOT não existe depois que o código começa a executar.
Na minha cabeça (posso estar errado) o problema é que se o código muda, daí vc tem que refazer o PGO para refletir o novo código. Se o código muda pouco no problem. Se muda muito aí complica.
Agora para concluir, minhas pesquisas com o PGO do GraalVM e da ZingVM (ReadyNow) mostraram uma melhorar de no máximo 50%. Ou seja, não chega perto do JIT em tempo de execução não. É uma ajuda, mas não é a solução para não precisar de JIT.
NOTE: PGO = Profile-guided optimizations