Estou fazendo um projeto em que preciso que todas as chamadas de API levem menos de 1s, mas estou enfrentando um problema com a primeira chamada em cada rota mais lenta que as seguintes.
Atualmente, a primeira chamada para / login leva 3,6s e as próximas levam 170ms e o mesmo para todas as outras rotas.
Descobri usando -XX:+TraceClassLoading
isso na primeira chamada, as classes foram carregadas na memória e isso causou um problema de desempenho.
No entanto, não encontrei uma maneira fácil de carregar todas as classes na inicialização e, para cada novo serviço, preciso adicionar uma chamada de aquecimento em um ApplicationRunner.
Alguém tem uma solução para carregar automaticamente as classes de um aplicativo SpringBoot ou aquecer todas as suas rotas?
invokedynamic
e sabemos que a resolução é lenta na primeira chamada para elas (temos dezenas de milhares de chamadas, que sem essa primeira chamada acumulam dezenas de segundos).Respostas:
O carregamento de classe do Java é lento. Isso significa que uma classe é carregada apenas pela JVM quando e quando necessário.
Se você deseja forçá-lo a carregar ansiosamente classes, basta referenciá-las. Uma maneira de fazer isso é percorrer o conteúdo do jar ou os arquivos de classe para obter os nomes das classes e usá-los para chamar
Class.forName(className)
.Além disso, se o tempo e o desempenho da inicialização forem muito importantes para o seu caso de uso, convém procurar soluções de compilação antecipadamente , como o GraalVM , ou reduzir o limite do JIT para compilação (
-XX:CompileThreshold
).fonte
JIT
é sem sentido nas primeiras invocações.GraalVM
é bom, mas observe o número de problemas no github: assim que você passar de um projeto de sandbox para algo maior (eu estou olhando sua reflexão, principalmente), você sentirá alguma dor, finalmente. meu ponto é: trocar para o GraalVM não é um simples estalar de dedos.Para mim, a única opção viável que você tem é
class data sharing
espalhada pelo JEP 310 , JEP 341 e JEP 350 , mas isso requer o java-13 provavelmente. Estamos testando isso internamente no meu local de trabalho (principalmente por diversão, não vou mentir) e os resultados parecem bons até agora.A outra opção está chamando seus terminais quando o aplicativo é iniciado - se essa é uma opção. Novamente, é para nós, por exemplo: nós os chamamos com dados fictícios algumas centenas de vezes para aquecer o código. Mas, ao mesmo tempo, temos serviços onde isso seria impossível - é por isso que a exploração
CDS
também.fonte