Slide 1

Slide 1 text

Sua aplicação Java até 60x mais rápida e sem reescrever o código Elder Moraes Developer Advocate @elderjava

Slide 2

Slide 2 text

@elderjava 2 IMAGENS NATIVAS • O que são? • Pra que servem? • O que comem? • Posso passar no cabelo?

Slide 3

Slide 3 text

@elderjava 3 Demo: até 60x mais rápido

Slide 4

Slide 4 text

@elderjava 4 Aviso: esta *não* é uma palestra sobre Graal VM! Esta é! https://youtu.be/SivvH93gcco

Slide 5

Slide 5 text

@elderjava 5 Obrigado pelas suas perguntas!

Slide 6

Slide 6 text

@elderjava 6 Um pouquinho de contexto

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

@elderjava 8 Pra começar

Slide 9

Slide 9 text

@elderjava 9 O que é uma imagem nativa? É uma tecnologia que utiliza AOT para compilar código Java para um executável standalone

Slide 10

Slide 10 text

@elderjava 10 Como uma imagem nativa é gerada? • Através do Native Image Builder • Ele analisa estaticamente todas as classes e suas dependências

Slide 11

Slide 11 text

@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

Slide 12

Slide 12 text

@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

Slide 13

Slide 13 text

@elderjava 13 Não! Precisa de JVM pra rodar uma imagem nativa?

Slide 14

Slide 14 text

@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.

Slide 15

Slide 15 text

@elderjava 15 Limitações

Slide 16

Slide 16 text

@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"

Slide 17

Slide 17 text

@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

Slide 18

Slide 18 text

@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

Slide 19

Slide 19 text

@elderjava 19 1. Features que funcionam, mas requerem configuração

Slide 20

Slide 20 text

@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

Slide 21

Slide 21 text

@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

Slide 22

Slide 22 text

@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

Slide 23

Slide 23 text

@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

Slide 24

Slide 24 text

@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

Slide 25

Slide 25 text

@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

Slide 26

Slide 26 text

@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

Slide 27

Slide 27 text

@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

Slide 28

Slide 28 text

@elderjava 28 2. Features que podem funcionar de modo diferente

Slide 29

Slide 29 text

@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

Slide 30

Slide 30 text

@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

Slide 31

Slide 31 text

@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

Slide 32

Slide 32 text

@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

Slide 33

Slide 33 text

@elderjava 33 Finalizers • Está como deprecated desde o Java 9 • Implementação complexa para imagens nativas 2. Features que podem funcionar de modo diferente

Slide 34

Slide 34 text

@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

Slide 35

Slide 35 text

@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

Slide 36

Slide 36 text

@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

Slide 37

Slide 37 text

@elderjava 37 3. Features que não funcionam

Slide 38

Slide 38 text

@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

Slide 39

Slide 39 text

@elderjava 39 Security Manager • Não implementado em imagens nativas 3. Features que não funcionam

Slide 40

Slide 40 text

@elderjava 40 Imagem Nativa vs JVM

Slide 41

Slide 41 text

@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

Slide 42

Slide 42 text

@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

Slide 43

Slide 43 text

@elderjava 43 Ué, então porque não usar imagens nativas para tudo?

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

@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?

Slide 46

Slide 46 text

@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?

Slide 47

Slide 47 text

@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?

Slide 48

Slide 48 text

@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?

Slide 49

Slide 49 text

@elderjava 49 Quando utilizar imagens nativas?

Slide 50

Slide 50 text

@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?

Slide 51

Slide 51 text

@elderjava 51 Quarkus & Imagens Nativas

Slide 52

Slide 52 text

@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

Slide 53

Slide 53 text

@elderjava 53 Mandrel & Graal VM

Slide 54

Slide 54 text

@elderjava 54

Slide 55

Slide 55 text

@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

Slide 56

Slide 56 text

@elderjava 56 Mais demos

Slide 57

Slide 57 text

@elderjava 57 developers.redhat.com/register

Slide 58

Slide 58 text

@elderjava 58 Obrigado!