Personalizar o comportamento de startup de runtime para as funções do Lambda
Esta página descreve as configurações específicas das funções do Java no AWS Lambda. É possível usar essas configurações para personalizar o comportamento de inicialização de runtime do Java. Isso pode reduzir a latência geral da função e melhorar a performance geral da função sem a necessidade de modificar qualquer código.
Seções
Entender a variável de ambiente JAVA_TOOL_OPTIONS
No Java, o Lambda é compatível com a variável de ambiente JAVA_TOOL_OPTIONS para definir variáveis adicionais da linha de comando no Lambda. É possível usar essa variável de ambiente de várias maneiras, como para personalizar configurações de compilação em camadas. O exemplo a seguir demonstra como usar a variável de ambiente JAVA_TOOL_OPTIONS para esse caso de uso.
Exemplo: personalizar as configurações de compilação em camadas
A compilação em camadas é um recurso da máquina virtual Java (JVM). É possível usar configurações específicas de compilação em camadas para fazer o melhor uso dos compiladores just-in-time (JIT) da JVM. Normalmente, o compilador C1 é otimizado para um tempo de inicialização rápido. O compilador C2 é otimizado para a melhor performance geral, mas também usa mais memória e leva mais tempo para alcançá-la. Existem cinco níveis diferentes de compilação em camadas. No nível 0, a JVM interpreta o código de bytes do Java. No nível 4, a JVM usa o compilador C2 para analisar os dados de criação de perfil coletados durante a inicialização da aplicação. Com o tempo, ele monitora o uso do código para identificar as melhores otimizações.
Personalização do nível de compilação em camadas pode ajudar a ajustar a performance da sua função do Java. Para funções pequenas que são executadas rapidamente, definir a compilação em camadas para o nível 1 pode ajudar a melhorar a performance da inicialização a frio fazendo com que a JVM use o compilador C1. Essa configuração produz rapidamente código nativo otimizado, mas não gera qualquer dado de criação de perfil e nunca usa o compilador C2. Para funções maiores e computacionalmente intensivas, definir a compilação em camadas para o nível 4 maximiza a performance geral às custas de consumo adicional de memória e de trabalho adicional de otimização durante as primeiras invocações após o provisionamento de cada ambiente de execução do Lambda.
Para runtimes do Java 11 e versões anteriores, o Lambda usa as configurações padrão de compilação em camadas da JVM. Por padrão, para o Java 17 e o Java 21, o Lambda configura a JVM para interromper a compilação em camadas no nível 1. A partir do Java 25, o Lambda ainda interrompe a compilação em camadas no nível 1 por padrão, exceto ao usar o SnapStart ou a simultaneidade provisionada, caso em que as configurações padrão da JVM são usadas. Isso melhora a performance do SnapStart e da simultaneidade provisionada sem incorrer em uma penalidade de inicialização a frio, já que a compilação hierárquica é realizada fora do caminho de chamada nesses casos. Para maximizar esse benefício, é possível usar caminhos de código de execução primária durante a inicialização da função para acionar o JIT antes de tirar o snapshot do SnapStart ou quando os ambientes de execução de simultaneidade provisionada são pré-provisionados. Para obter mais informações, consulte a postagem do blog Otimização daperformance da inicialização a frio do AWS Lambda com o uso de estratégias avançadas de preparação com o SnapStart
Para personalizar as configurações de compilação em camadas (console)
-
Abra a página Funções
no console do Lambda. -
Escolha uma função do Java para a qual você deseja personalizar a compilação em camadas.
-
Escolha a guia Configuração e, em seguida, escolha Variáveis de ambiente no menu à esquerda.
-
Selecione a opção Editar.
-
Escolha Add environment variable (Adicionar variável de ambiente).
-
Na chave, insira
JAVA_TOOL_OPTIONS. No valor, insira-XX:+TieredCompilation -XX:TieredStopAtLevel=1.
-
Escolha Salvar.
nota
Também é possível usar o Lambda SnapStart para mitigar problemas de inicialização a frio. O SnapStart usa snapshots em cache do ambiente de execução para melhorar significativamente a performance da inicialização. Para obter mais informações sobre os recursos, limitações e regiões compatíveis com o SnapStart, consulte Aprimoramento da performance de inicialização com o Lambda SnapStart.
Exemplo: personalização do comportamento do GC usando JAVA_TOOL_OPTIONS
Os runtimes do Java 11 usam o SerialJAVA_TOOL_OPTIONS para alterar o GC padrão. É possível escolher entre o Parallel GC e o Shenandoah GC
Por exemplo, se sua workload usa mais memória e diversas CPUs, considere usar o Parallel GC para obter melhor performance. É possível fazer isso ao anexar o seguinte ao valor da variável de ambiente JAVA_TOOL_OPTIONS:
-XX:+UseParallelGC
Se a sua workload tiver muitos objetos de curta duração, será possível se beneficiar de menor consumo de memória ativando o modo geracional do coletor de lixo Shenandoah introduzido no Java 25. Para fazer isso, anexe o valor a seguir ao valor da variável de ambiente JAVA_TOOL_OPTIONS:
-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
Patch do Log4j para o Log4Shell
Os runtimes do Lambda para Java 8, 11, 17 e 21 incluem um patch para mitigar a vulnerabilidade do Log4Shell (CVE-2021-44228) no Log4j, uma estrutura popular de registro em log em Java. Esse patch gera uma sobrecarga de performance na inicialização a frio. Se você estiver usando uma versão corrigida do Log4j (versão 2.17.0 ou posterior), é possível desabilitar esse patch para melhorar a performance da inicialização a frio. Para desabilitar esse aviso, defina a variável de ambiente AWS_LAMBDA_DISABLE_CVE_2021_44228_PROTECTION como true.
A partir do Java 25, os runtimes do Lambda não incluem mais o patch Log4Shell. É necessário verificar se você está usando o Log4j versão 2.17.0 ou posterior.
Caches antecipados (AOT) e CDS
A partir do Java 25, o runtime do Lambda inclui um cache antecipado (AOT) para o cliente de interface de runtime Java (RIC), um componente de runtime que sonda ativamente os eventos da API de runtime do Lambda. Isso melhora a performance da inicialização a frio.
Os caches AOT são específicos para uma compilação da JVM. Quando o Lambda atualiza o runtime gerenciado, ele também atualiza o cache AOT para o RIC. No entanto, se você implantar seus próprios caches AOT, eles poderão ser invalidados ou resultar em um comportamento inesperado após uma atualização de runtime. Portanto, é altamente recomendável não usar caches AOT ao usar runtimes gerenciados. Para usar caches AOT, você deve implantar suas funções usando imagens de contêiner.
Os caches AOT não podem ser usados com os caches de compartilhamento de dados de classe (CDS). Se você implantar caches de CDS em sua função do Lambda, o Lambda desabilitará o cache AOT.