Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sua aplicação Java até 60x mais rápida e sem reescrever o código

Sua aplicação Java até 60x mais rápida e sem reescrever o código

Em um mundo com aplicações cada vez mais distribuídas e sem controle de estado, um dos grandes desafios está ligado à performance (seja no tempo de inicialização ou mesmo na resposta à primeira request). Foi dentro deste contexto que durante muito tempo o Java foi uma dúvida em abordagens como serverless, microservices e containers. Mas esses tempos acabaram! Hoje não apenas temos plataformas que levam o Java a um nível de performance jamais imaginado, como também temos algo que possibilita dar um passo além: é a imagem nativa. Venha para esta sessão e aprenda o que dá e o que não dá pra fazer com esta abordagem, e como você pode rodar seu código 60x mais rápido ainda hoje.

Cad9d9d8998f49269ce4f28a018ba53e?s=128

Elder Moraes

June 07, 2021
Tweet

Transcript

  1. Sua aplicação Java até 60x mais rápida e sem reescrever

    o código Elder Moraes Developer Advocate @elderjava
  2. @elderjava 2 IMAGENS NATIVAS • O que são? • Pra

    que servem? • O que comem? • Posso passar no cabelo?
  3. @elderjava 3 Demo: até 60x mais rápido

  4. @elderjava 4 Aviso: esta *não* é uma palestra sobre Graal

    VM! Esta é! https://youtu.be/SivvH93gcco
  5. @elderjava 5 Obrigado pelas suas perguntas!

  6. @elderjava 6 Um pouquinho de contexto

  7. @elderjava 7 Fonte: https://www.graalvm.org/community/opensource Native Image Builder

  8. @elderjava 8 Pra começar

  9. @elderjava 9 O que é uma imagem nativa? É uma

    tecnologia que utiliza AOT para compilar código Java para um executável standalone
  10. @elderjava 10 Como uma imagem nativa é gerada? • Através

    do Native Image Builder • Ele analisa estaticamente todas as classes e suas dependências
  11. @elderjava 11 Como uma imagem nativa é gerada? • São

    mapeados todos os métodos e bibliotecas envolvidas no runtime • Então ele compila (AOT) todo esse código, gerando um executável nativo para um OS e arquitetura específicos
  12. @elderjava 12 O que está incluído em uma imagem nativa?

    • Classes da aplicação • Classes das dependências • Classes de bibliotecas runtime • Código estático nativo do JDK
  13. @elderjava 13 Não! Precisa de JVM pra rodar uma imagem

    nativa?
  14. @elderjava 14 Eita! Então como funciona? • Imagens nativas possuem

    um sistema de runtime chamado Substrate VM • Alguns dos seus componentes são: gerenciamento de memória, thread scheduling, GC, etc.
  15. @elderjava 15 Limitações

  16. @elderjava 16 Limitações Premissas • Todo código de runtime tem

    que ser conhecido em tempo de compilação • Nenhum código novo é carregado em runtime • Como em toda otimização, nem toda aplicação é “otimizável"
  17. @elderjava 17 4 grupos de compatibilidade 1. Features que funcionam,

    mas requerem configuração 2. Features que podem funcionar de modo diferente 3. Features que não funcionam 4. O restante (funciona out of the box) Limitações
  18. @elderjava 18 4 grupos de compatibilidade 1. Features que funcionam,

    mas requerem configuração 2. Features que podem funcionar de modo diferente 3. Features que não funcionam 4. O restante (funciona out of the box) Limitações
  19. @elderjava 19 1. Features que funcionam, mas requerem configuração

  20. @elderjava 20 Dynamic class loading • Ex: Class.forName(“myClass”) • “myClass"

    precisa estar em um arquivo de configuração • Se a classe não estiver disponível, lança ClassNotFoundException 1. Features que funcionam, mas requerem con fi guração
  21. @elderjava 21 Reflection • Classes, métodos e campos acessados via

    reflection precisam ser conhecidos ahead- of-time • O Native Image Builder identificará as chamadas à Reflection API para mapear esses elementos 1. Features que funcionam, mas requerem con fi guração
  22. @elderjava 22 Reflection • Se a análise falhar, os elementos

    acessados via reflection devem ser informados em um arquivo de configuração • Class initializers podem usar reflection sem restrições 1. Features que funcionam, mas requerem con fi guração
  23. @elderjava 23 Dynamic Proxy • É suportado desde que o

    bytecode seja gerado ahead-of-time • Ou seja, a lista de interfaces que definem os proxies precisa ser conhecida em build time 1. Features que funcionam, mas requerem con fi guração
  24. @elderjava 24 Dynamic Proxy • Chamadas mapeadas • java.lang.reflect.Proxy.newProxyInstance •

    java.lang.reflect.Proxy.getProxyClass • Se a análise estática falhar, a lista de interfaces deve ser informada via arquivo de configuração 1. Features que funcionam, mas requerem con fi guração
  25. @elderjava 25 JNI (Java Native Interface) • Muito semelhante ao

    funcionamento do Reflection (acesso objetos, classes, métodos e campos) • Pelo mesmo motivo, os itens acessados devem ser informados via arquivo de configuração 1. Features que funcionam, mas requerem con fi guração
  26. @elderjava 26 JNI (Java Native Interface) • Como alternativa, o

    Native Image possui sua própria interface nativa, bem mais simples que o JNI • Ref: org.graalvm.nativeimage.c 1. Features que funcionam, mas requerem con fi guração
  27. @elderjava 27 Serialização • Os metadados devem ser informados em

    um arquivo de configuração 1. Features que funcionam, mas requerem con fi guração
  28. @elderjava 28 2. Features que podem funcionar de modo diferente

  29. @elderjava 29 Signal Handlers • Por default, nenhum signal handler

    é registrado em uma imagem nativa • Para ser registrado, o usuário deve fazê-lo explicitamente 2. Features que podem funcionar de modo diferente
  30. @elderjava 30 Signal Handlers • Para registrar, passe a option

    —install- exit-handlers para o Native Image Builder • Esta option dá acesso aos mesmos signal handlers que a JVM daria 2. Features que podem funcionar de modo diferente
  31. @elderjava 31 Class Initializers • Por default, as classes são

    inicializadas no runtime da imagem • Garante compatibilidade, mas limita otimização • Se inicializar em build time, melhora o tempo de startup e pico de performance 2. Features que podem funcionar de modo diferente
  32. @elderjava 32 Class Initializers • Para ajustes (para uma classe,

    uma package ou todas as classes): • --initialize-at-build-time • --initialize-at-run-time 2. Features que podem funcionar de modo diferente
  33. @elderjava 33 Finalizers • Está como deprecated desde o Java

    9 • Implementação complexa para imagens nativas 2. Features que podem funcionar de modo diferente
  34. @elderjava 34 Threads • Métodos do java.lang.Thread que viraram deprecated

    há muito tempo não são implementados em imagens nativas • Ex: Thread.stop() (deprecated desde 1.2) 2. Features que podem funcionar de modo diferente
  35. @elderjava 35 Debug e Monitoramento • Normalmente são feitos através

    de interfaces que assumem a presença do bytecode durante o runtime • O que não ocorre com imagens nativas 2. Features que podem funcionar de modo diferente
  36. @elderjava 36 Debug e Monitoramento • Opção: utilize ferramentas também

    nativas • Ex: GDB (GNU Debugger) e VTune Profiler 2. Features que podem funcionar de modo diferente
  37. @elderjava 37 3. Features que não funcionam

  38. @elderjava 38 invokedynamic • O método invocado pode mudar em

    runtime (o que não é possível com imagens nativas) 3. Features que não funcionam
  39. @elderjava 39 Security Manager • Não implementado em imagens nativas

    3. Features que não funcionam
  40. @elderjava 40 Imagem Nativa vs JVM

  41. @elderjava 41 Startup mais rápido • Não há classloading (todas

    as classes já foram carregadas, linkadas e inicializadas) • Não há interpretação de código • Não há JIT • Parte da heap já foi gerada na compilação Imagem Nativa vs JVM
  42. @elderjava 42 Menor footprint de memória • Não há metadado

    para as classes carregadas • Não há dados de profiling para otimizações do JIT • Não há cache de código interpretado • Não há estruturas JIT Imagem Nativa vs JVM
  43. @elderjava 43 Ué, então porque não usar imagens nativas para

    tudo?
  44. @elderjava 44 Porque não existem balas de prata!

  45. @elderjava 45 Não há suporte para: • JVM TI (Java

    Virtual Machine Tool Interface) • Java Agents • JMX (Java Management Extensions) • JFR (Java Flight Recorder) Porque não usar imagens nativas para tudo?
  46. @elderjava 46 Bom apenas para heaps pequenas: • O processo

    de GC é feito pelo SerialGC disponível na SubstrateVM - bem mais limitado que um GC “full” • Se a heap for muito grande, o GC vai degradar a performance da aplicação Porque não usar imagens nativas para tudo?
  47. @elderjava 47 Não há otimização em runtime • Não há

    JIT • Toda a otimização feita na compilação é final Porque não usar imagens nativas para tudo?
  48. @elderjava 48 Não há suporte para head dump e thread

    dump • Ou há… mas apenas na versão Enterprise Porque não usar imagens nativas para tudo?
  49. @elderjava 49 Quando utilizar imagens nativas?

  50. @elderjava 50 Em aplicações que: • Sejam pequenas • Possam

    ser invocadas múltiplas vezes em curtos períodos de tempo • Possuam um ciclo de vida curto • Ex: CLI apps e serverless functions Quando utilizar imagens nativas?
  51. @elderjava 51 Quarkus & Imagens Nativas

  52. @elderjava 52 • Todas as otimizações do Quarkus *independem* do

    uso de imagens nativas • Mas, se quiser utilizar, ele é 100% compatível (incluindo suas extensões) • Basta ter o Native Image Builder disponível (via Graal VM ou Mandrel) Quarkus & Imagens Nativas
  53. @elderjava 53 Mandrel & Graal VM

  54. @elderjava 54

  55. @elderjava 55 • Fork do Graal VM CE • Em

    linhas gerais: OpenJDK + Native Image Builder • Foco no suporte ao Quarkus • Melhor suporte ao clientes Red Hat • Contribuição para todo o ecossistema Graal VM CE Mandrel & Graal VM
  56. @elderjava 56 Mais demos

  57. @elderjava 57 developers.redhat.com/register

  58. @elderjava 58 Obrigado!